有没有更有效的方法来搜索特定像素的图像?

Is there a more efficient way to search an image for a specific pixel?

我目前正在使用 python 和 openCV 进行计算机视觉项目。

我需要在一张大小约为 620x420 像素的图像中搜索最靠近图像底部的绿色像素。之前轮廓分析的图像中有多个绿色像素(例如100)。

这是一个示例图片:

我已经用下面的代码实现了它:

    # Search for the most bottom contour point
    xLowestContour = 0                         # x coordinate of the lowest contour point
    yLowestContour = 0                         # y coordinate of the lowest contour point
    for y in range(roi_h):                     # roi_h is the heigth of the image
        for x in range(roi_w):                 # roi_w is the width of the image
            (b, g, r) = roi_copy[y, x]         # roi_copy is the actual image
            if g == 255 and b == 0 and r == 0:
                xLowestContour = x
                yLowestContour = y

此代码有效。但是它有一个大问题。看起来这种在图像中搜索特定像素的方式非常低效。使用此代码片段,帧速率从 25 FPS 下降到 2 FPS。使用此代码片段时,CPU 利用率仅为 10%。

有没有更高效的方法来做这个操作?我还想利用更多 CPU 的能力并获得更高的帧率。

避免循环,使用numpy!

你可以使用 numpy 的 argwhere()。语句 return 是满足特定条件的坐标数组。

a = np.argwhere(image == [0,255,0])

# returns array a with three columns,
# since you need only the coordinates, you can delete the third column:
a = np.delete(a, 2, 1)  # delete third column in a

a 会 return 以下示例:

array([[  0,  18],
       [  0,  19],
       [  0,  21],
       ...,
       [539, 675],
       [539, 677],
       [539, 677]], dtype=int64)

以上 returns 坐标,其中存在绿色像素值 [0, 255, 0]

根据return编辑的坐标,可以过滤靠近图像底部的那些。

def get_last_pixel(image, rgb):
    color_rows, color_cols = np.where((image[:, :, 0] == rgb[0]) & (image[:, :, 1] == rgb[1]) & (
        image[:, :, 2] == rgb[2]))  # Get coordinates of pixels wit the requested rgb value
    if len(color_rows) == 0:
        raise Exception("no pixels of the requested color")
    row_max = np.argmax(color_rows)  # Find the index of the biggest row
    pixel_coords = (color_rows[row_max], color_cols[row_max])
    return pixel_coords


example_input = cv2.imread("example_input.png")
last_green = get_last_pixel(example_input, (0, 255, 0))
example_output = cv2.circle(
    example_input, last_green[::-1], radius=5, color=(0, 0, 255), thickness=1)
cv2.imwrite("example_output.png", example_output)

示例输入:

示例输出: