有没有更有效的方法来搜索特定像素的图像?
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)
示例输入:
示例输出:
我目前正在使用 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)
示例输入:
示例输出: