Python中的快速RGB阈值处理(可能是一些智能的OpenCV代码?)

Hap*_*ppy 4 python rgb opencv threshold

我需要对大量图像进行一些快速阈值处理,每个RGB通道都有一个特定的范围,即去除(使黑色)不在[100; 110]中的所有R值,所有G值都不在[80; 85]和所有B值不在[120; 140]

使用到OpenCV的python绑定为我提供了一个快速阈值处理,但它将所有三个RGP通道阈值设置为单个值:

cv.Threshold(cv_im,cv_im,threshold+5, 100,cv.CV_THRESH_TOZERO_INV)
cv.Threshold(cv_im,cv_im,threshold-5, 100,cv.CV_THRESH_TOZERO)
Run Code Online (Sandbox Code Playgroud)

或者,我尝试通过将图像从PIL转换为numpy来手动完成:

arr=np.array(np.asarray(Image.open(filename).convert('RGB')).astype('float'))
for x in range(img.size[1]):
    for y in range(img.size[0]):
        bla = 0
        for j in range(3):
            if arr[x,y][j] > threshold2[j] - 5 and arr[x,y][j] < threshold2[j] + 5 :
                bla += 1
        if bla == 3:
            arr[x,y][0] = arr[x,y][1] = arr[x,y][2] = 200
        else:
            arr[x,y][0] = arr[x,y][1] = arr[x,y][2] = 0
Run Code Online (Sandbox Code Playgroud)

虽然这是按预期工作的,但速度非常慢!

关于如何快速实现这一点的任何想法?

非常感谢,Bjarke

mev*_*ron 5

我认为inRange opencv方法是你感兴趣的.它可以让你同时设置多个阈值.

所以,你可以使用你的例子

# Remember -> OpenCV stores things in BGR order
lowerBound = cv.Scalar(120, 80, 100);
upperBound = cv.Scalar(140, 85, 110);

# this gives you the mask for those in the ranges you specified,
# but you want the inverse, so we'll add bitwise_not...
cv.InRange(cv_im, lowerBound, upperBound, cv_rgb_thresh);
cv.Not(cv_rgb_thresh, cv_rgb_thresh);
Run Code Online (Sandbox Code Playgroud)

希望有所帮助!


jte*_*ace 5

你可以在一个与numpy的做更快的方法,如果你不使用循环。

这是我想出的:

def better_way():
    img = Image.open("rainbow.jpg").convert('RGB')
    arr = np.array(np.asarray(img))

    R = [(90,130),(60,150),(50,210)]
    red_range = np.logical_and(R[0][0] < arr[:,:,0], arr[:,:,0] < R[0][1])
    green_range = np.logical_and(R[1][0] < arr[:,:,0], arr[:,:,0] < R[1][1])
    blue_range = np.logical_and(R[2][0] < arr[:,:,0], arr[:,:,0] < R[2][1])
    valid_range = np.logical_and(red_range, green_range, blue_range)

    arr[valid_range] = 200
    arr[np.logical_not(valid_range)] = 0

    outim = Image.fromarray(arr)
    outim.save("rainbowout.jpg")


import timeit
t = timeit.Timer("your_way()", "from __main__ import your_way")
print t.timeit(number=1)

t = timeit.Timer("better_way()", "from __main__ import better_way")
print t.timeit(number=1)
Run Code Online (Sandbox Code Playgroud)

省略的your_way函数是上面代码的略微修改版本。这样可以更快地运行:

$ python pyrgbrange.py 
10.8999910355
0.0717720985413
Run Code Online (Sandbox Code Playgroud)

那是10.9秒vs.0.07秒。