I am somehow new to python and would like to get rid of use of for loop as it makes the program very slow. So I would like vectorize it. however, I am not sure how would I use it with two conditions Here I shared the code and would like someone could hit me..
image to be imported
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
def nothing(color):
pass
cv.namedWindow('Trackbar ')
cv.resizeWindow('Trackbar',800,200)
cv.createTrackbar('v_min','Trackbar ',0,255,nothing)
cv.createTrackbar('v_max','Trackbar ',0,255,nothing)
while True:
img_ = cv.imread('sat.png',cv.IMREAD_COLOR)
img_np=np.array(img_)
img2_np=np.array(img_)
value_min=cv.getTrackbarPos('v_min','Trackbar ')
value_max=cv.getTrackbarPos('v_max','Trackbar ')
height, width = img_np.shape[:2]
for j in range (0,width) :
for i in range (0,height):
for k in range (0,2):
if (value_min < img_np[i,j,k] <= value_max):
img2_np[i,j] = ((img_np[i,j]-value_min)/(value_max-value_min))*255
else:
img2_np[i,j] = 0
#Here is the vectorization to remove all for and if loop (what I think )
# img_np[(value_min < img_np.any() <= value_max)]=((img_np-value_min)/(value_max-value_min))*255 | img_np[(value_min > img_np.any() >= value_max)]=0
cv.imshow('FINAL IMAGE',img_np)
cv.imshow('image',img_)
kk = cv.waitKey(1000) & 0xFF # large wait time to remove freezing
if kk == 113 or kk == 27:
break
I am expecting to convert or I mean to remove all (for, if/else loop) with vectorize so less time.. so I tried first to with one if condition and seems working however, when I tried to add with two conditions like (|) else seems not working
I am somehow new to python and would like to get rid of use of for loop as it makes the program very slow. So I would like vectorize it. however, I am not sure how would I use it with two conditions Here I shared the code and would like someone could hit me..
image to be imported
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
def nothing(color):
pass
cv.namedWindow('Trackbar ')
cv.resizeWindow('Trackbar',800,200)
cv.createTrackbar('v_min','Trackbar ',0,255,nothing)
cv.createTrackbar('v_max','Trackbar ',0,255,nothing)
while True:
img_ = cv.imread('sat.png',cv.IMREAD_COLOR)
img_np=np.array(img_)
img2_np=np.array(img_)
value_min=cv.getTrackbarPos('v_min','Trackbar ')
value_max=cv.getTrackbarPos('v_max','Trackbar ')
height, width = img_np.shape[:2]
for j in range (0,width) :
for i in range (0,height):
for k in range (0,2):
if (value_min < img_np[i,j,k] <= value_max):
img2_np[i,j] = ((img_np[i,j]-value_min)/(value_max-value_min))*255
else:
img2_np[i,j] = 0
#Here is the vectorization to remove all for and if loop (what I think )
# img_np[(value_min < img_np.any() <= value_max)]=((img_np-value_min)/(value_max-value_min))*255 | img_np[(value_min > img_np.any() >= value_max)]=0
cv.imshow('FINAL IMAGE',img_np)
cv.imshow('image',img_)
kk = cv.waitKey(1000) & 0xFF # large wait time to remove freezing
if kk == 113 or kk == 27:
break
I am expecting to convert or I mean to remove all (for, if/else loop) with vectorize so less time.. so I tried first to with one if condition and seems working however, when I tried to add with two conditions like (|) else seems not working
Share Improve this question edited Nov 21, 2024 at 10:58 Momo R asked Nov 21, 2024 at 0:47 Momo RMomo R 113 bronze badges 4 |2 Answers
Reset to default 0Your code using for loops in that order is the worst possible way you could do it unless the images being processed have width, height of 2 or less.
for j in range (0,width) :
for i in range (0,height):
for k in range (0,2):
if (value_min < img_np[i][j][k] <= value_max):
img2_np[i][j] = ((img_np[i][j]-value_min)/(value_max-value_min))*255
else:
img2_np[i][j] = 0
The innermost loop has maximal setup overheads that way around.
It should be replaced by
for k in range (0,2):
for j in range (0,width) :
for i in range (0,height):
if (value_min < img_np[i][j][k] <= value_max):
img2_np[i][j][k] = ((img_np[i][j][k]-value_min)/(value_max-value_min))*255
else:
img2_np[i][j][k] = 0
I don't know how good the optimiser is in Python at removing loop invariants and strength reduction so it might also be worth manually moving the scaling out of the loop and multiplying rather than dividing. Division is the most expensive binary arithmetic operation ~10x slower than +,-,*
.
scalefactor = 255/(value_max-value_min)
...
if (value_min < img_np[i][j][k] <= value_max):
img2_np[i][j][k] = ((img_np[i][j][k]-value_min)*scalefactor
else:
img2_np[i][j][k] = 0
You also need to check the memory allocation rules for 3D arrays in Python to ensure you are making sequential memory access if the arrays are large.
Without actually testing this, this change should work - assuming in 1 condition more or less works.
img_np2 = np.zeros_like(img_np2) # default 0s
cond = (value_min < img_np) & (img_np <= value_max)
img_np2[cond] = ((img_np[cond]-value_min)/(value_max-value_min))*255
alternatively
img_np2 = np.where(cond, ((img_np-value_min)/(value_max-value_min))*255, 0)
a<x<=b
only works with scalar x
. for array, it needs to be separated into two clauses, ()&()
.
The where
version evaluates at all points, but that should be ok here. Sometimes we want conditional evaluation to avoid things like run time errors, divide by zero, etc. Then we need to use the first version, or use the where
clause in a ufunc
(like np.divide
).
img2_np[i][j][k]
in your if/else statement? I'm not quite sure what you want to happen when k=0 gives you theif
side and k=1 gives you the else side. (ps. In numpy, it's equivalent and more conventional to writeimg2_np[i, j, k]
wheni
,j
, andk
are integers. – Frank Yellin Commented Nov 21, 2024 at 1:19