最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

numpy - Vectorization with ifelse conditions Python - Stack Overflow

programmeradmin2浏览0评论

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
  • 1 You're code's not quite making sense. Did you mean do you 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 the if side and k=1 gives you the else side. (ps. In numpy, it's equivalent and more conventional to write img2_np[i, j, k] wheni, j, and k are integers. – Frank Yellin Commented Nov 21, 2024 at 1:19
  • @FrankYellin Thanks for your comment, I edited the indices to be written directly [i,j,k].. Well, the third index is not a big deal for me.. i mean I just would like to replace each element ((img_np[i][j]-value_min)/(value_max-value_min))*255 when if condition exists, otherwise replace with zeros It is working with for and if loop but super slow so kindly asking to how to vectorize it. Let me know Thanks – Momo R Commented Nov 21, 2024 at 10:57
  • Please provide a minimal reproducible example that we can run. That is, a little code to generate a realistic array (can be random but should otherwise be like your real ones) and min/max, and then the transformation code. Don't load a file we don't have, and get rid of the cv stuff and user interaction that aren't relevant to the question. – no comment Commented Nov 21, 2024 at 11:35
  • What's the point of the k=0 iteration if the k=1 iteration overwrites img2_np[i,j] anyway? – no comment Commented Nov 21, 2024 at 11:58
Add a comment  | 

2 Answers 2

Reset to default 0

Your 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).

发布评论

评论列表(0)

  1. 暂无评论