首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python中的快速RGB阈值(可能是一些智能的OpenCV代码?)

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

Stack Overflow用户
提问于 2011-10-11 15:11:45
回答 4查看 13.4K关注 0票数 4

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

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

代码语言:javascript
复制
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)

或者,我尝试手动将图像从PIL转换为numpy:

代码语言:javascript
复制
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

虽然这是预期的工作,但它是可怕的缓慢!

关于如何快速实现这一点,有什么想法吗?

非常感谢,Bjarke

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-10-11 21:12:48

我认为您感兴趣的是inRange opencv方法。它将允许您同时设置多个阈值。

因此,在您的示例中,您将使用

代码语言:javascript
复制
# 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);

希望这能有所帮助!

票数 5
EN

Stack Overflow用户

发布于 2011-10-12 02:07:29

如果你不使用循环,你可以用更快的方式来做这件事。

这是我想出来的:

代码语言:javascript
复制
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)

省略的your_way函数是上面代码的略微修改版本。这种方式运行得更快:

代码语言:javascript
复制
$ python pyrgbrange.py 
10.8999910355
0.0717720985413

这是10.9秒而不是0.07秒。

票数 5
EN

Stack Overflow用户

发布于 2011-10-11 21:37:30

PIL point函数为图像的每个波段获取一个包含256个值的表,并将其用作映射表。它应该会很快。下面是在这种情况下如何应用它:

代码语言:javascript
复制
def mask(low, high):
    return [x if low <= x <= high else 0 for x in range(0, 256)]

img = img.point(mask(100,110)+mask(80,85)+mask(120,140))

numpy编辑:上面的输出与您的示例不同;我遵循的是描述而不是代码。下面是最新消息:

代码语言:javascript
复制
def mask(low, high):
    return [255 if low <= x <= high else 0 for x in range(0, 256)]

img = img.point(mask(100,110)+mask(80,85)+mask(120,140)).convert('L').point([0]*255+[200]).convert('RGB')

这将在图像上进行一些转换,在此过程中制作副本,但它仍然应该比对单个像素进行操作更快。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7722519

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档