查找图像中红色像素的坐标
Find the coordinates of red pixel in an image
Input picture
上图是我正在拍摄的样本输入,我想找到这张图片中所有红色像素的坐标并将其存储在一个列表中,然后,迭代这个列表并在每个像素周围画圈我们使用 OpenCV 的 cv2.circle 函数在图像中找到的坐标。我正在执行以下操作:
coord = []
for i in range(img.shape[0]):
for j in range(img.shape[1]):
if img[i,j,0]!=0 and img[i,j,1]!=0 and img[i,j,2]!=255:
img[i,j,0]=0
img[i,j,1]=0
img[i,j,2]=0
else:
img[i,j,0]=0
img[i,j,1]=0
img[i,j,2]=255
coord.append([i,j])
for l in range(len(coord)):
px=coord[l][0]
py=coord[l][1]
cv2.circle(img,(px,py),5,(0,255,255),1)
但是执行上述操作并不是在所有坐标上都画一个圆。我猜坐标的存储和访问有问题。谁能指出错误并帮助我。
I am getting the following output which isn't correct
你的条件写的不好。首先,最好在一个范围内搜索,如果像素值<10我们可以认为它是黑色的。
对于红色,我们可以检查 B 和 G 通道的值是否小于 < 10(您可以更改它),R 通道的值是否 > 220。
coord = []
for i in range(img.shape[0]):
for j in range(img.shape[1]):
if img[i,j,0]<10 and img[i,j,1]<10 and img[i,j,2]>220:
img[i,j,0]=0
img[i,j,1]=0
img[i,j,2]=255
coord.append([i,j])
else:
img[i,j,0]=0
img[i,j,1]=0
img[i,j,2]=0
for l in range(len(coord)):
px=coord[l][0]
py=coord[l][1]
cv2.circle(img,(py,px),5,(0,255,255),1)
你会在那里呆一整天 for
循环!使用环核进行形态学卷积会快很多。我可以向您展示如何在 ImageMagick 中快速完成,但您也可以使用 OpenCV.
进行同样的操作
基本命令如下:
magick stars.png -morphology convolve ring:3.5,4.5 result.png
我会再 运行 一次,这一次,请 ImageMagick 向我展示内核 - 希望你能看到 1s 形成一个内半径为 3.5 像素、外半径为 4.5 像素的环:
convert stars.png -define morphology:showkernel=1 -morphology convolve ring:3.5,4.5 result.png
输出
Kernel "Ring" of size 9x9+4+4 with values from 1 to 1
Forming a output range from 0 to 32 (Sum 32)
0: nan nan 1 1 1 1 1 nan nan
1: nan 1 1 nan nan nan 1 1 nan
2: 1 1 nan nan nan nan nan 1 1
3: 1 nan nan nan nan nan nan nan 1
4: 1 nan nan nan nan nan nan nan 1
5: 1 nan nan nan nan nan nan nan 1
6: 1 1 nan nan nan nan nan 1 1
7: nan 1 1 nan nan nan 1 1 nan
8: nan nan 1 1 1 1 1 nan nan
Anthony Thyssen here.
对形态学这门迷人的学科及其工作原理进行了精彩的描述
这是同一技术的 OpenCV Python 版本:
#!/usr/bin/env python3
import cv2
from skimage.draw import circle_perimeter
import numpy as np
# Load image
im = cv2.imread('stars.png')
# Ring shape structuring element 9x9 with a central circle radius 4 of 1s
selem = np.zeros((9, 9), dtype=np.uint8)
rr, cc = circle_perimeter(4, 4, 4)
selem[rr, cc] = 1
# Do the morphology just on red channel
dilated = cv2.dilate(im[...,2], selem, iterations=1)
# Put modified red channel back into original image and save
im[:,:,2] = dilated
cv2.imwrite('result.png', im)
结果同上
这里的主要问题是当写回那些圆圈时,你的 px
和 py
被调换了。你必须做 (py, px)
.
但是,此外,为了更快地找到红色像素(在我的机器上快 135 倍!),请结合使用
cv2.inRange
(生成二值mask图像,匹配像素为1,不匹配像素为0)
np.argwhere
(其中 returns 值为非零的矩阵的索引)
import cv2
import numpy as np
img = cv2.imread("RvegM.png")
red_pixels = np.argwhere(cv2.inRange(img, (0, 0, 250), (0, 0, 255)))
for px, py in red_pixels:
cv2.circle(img, (py, px), 5, (0, 255, 255), 1)
cv2.imwrite("out.png", img)
out.png 最终看起来像这样:
Input picture
上图是我正在拍摄的样本输入,我想找到这张图片中所有红色像素的坐标并将其存储在一个列表中,然后,迭代这个列表并在每个像素周围画圈我们使用 OpenCV 的 cv2.circle 函数在图像中找到的坐标。我正在执行以下操作:
coord = []
for i in range(img.shape[0]):
for j in range(img.shape[1]):
if img[i,j,0]!=0 and img[i,j,1]!=0 and img[i,j,2]!=255:
img[i,j,0]=0
img[i,j,1]=0
img[i,j,2]=0
else:
img[i,j,0]=0
img[i,j,1]=0
img[i,j,2]=255
coord.append([i,j])
for l in range(len(coord)):
px=coord[l][0]
py=coord[l][1]
cv2.circle(img,(px,py),5,(0,255,255),1)
但是执行上述操作并不是在所有坐标上都画一个圆。我猜坐标的存储和访问有问题。谁能指出错误并帮助我。
I am getting the following output which isn't correct
你的条件写的不好。首先,最好在一个范围内搜索,如果像素值<10我们可以认为它是黑色的。
对于红色,我们可以检查 B 和 G 通道的值是否小于 < 10(您可以更改它),R 通道的值是否 > 220。
coord = []
for i in range(img.shape[0]):
for j in range(img.shape[1]):
if img[i,j,0]<10 and img[i,j,1]<10 and img[i,j,2]>220:
img[i,j,0]=0
img[i,j,1]=0
img[i,j,2]=255
coord.append([i,j])
else:
img[i,j,0]=0
img[i,j,1]=0
img[i,j,2]=0
for l in range(len(coord)):
px=coord[l][0]
py=coord[l][1]
cv2.circle(img,(py,px),5,(0,255,255),1)
你会在那里呆一整天 for
循环!使用环核进行形态学卷积会快很多。我可以向您展示如何在 ImageMagick 中快速完成,但您也可以使用 OpenCV.
基本命令如下:
magick stars.png -morphology convolve ring:3.5,4.5 result.png
我会再 运行 一次,这一次,请 ImageMagick 向我展示内核 - 希望你能看到 1s 形成一个内半径为 3.5 像素、外半径为 4.5 像素的环:
convert stars.png -define morphology:showkernel=1 -morphology convolve ring:3.5,4.5 result.png
输出
Kernel "Ring" of size 9x9+4+4 with values from 1 to 1
Forming a output range from 0 to 32 (Sum 32)
0: nan nan 1 1 1 1 1 nan nan
1: nan 1 1 nan nan nan 1 1 nan
2: 1 1 nan nan nan nan nan 1 1
3: 1 nan nan nan nan nan nan nan 1
4: 1 nan nan nan nan nan nan nan 1
5: 1 nan nan nan nan nan nan nan 1
6: 1 1 nan nan nan nan nan 1 1
7: nan 1 1 nan nan nan 1 1 nan
8: nan nan 1 1 1 1 1 nan nan
Anthony Thyssen here.
对形态学这门迷人的学科及其工作原理进行了精彩的描述这是同一技术的 OpenCV Python 版本:
#!/usr/bin/env python3
import cv2
from skimage.draw import circle_perimeter
import numpy as np
# Load image
im = cv2.imread('stars.png')
# Ring shape structuring element 9x9 with a central circle radius 4 of 1s
selem = np.zeros((9, 9), dtype=np.uint8)
rr, cc = circle_perimeter(4, 4, 4)
selem[rr, cc] = 1
# Do the morphology just on red channel
dilated = cv2.dilate(im[...,2], selem, iterations=1)
# Put modified red channel back into original image and save
im[:,:,2] = dilated
cv2.imwrite('result.png', im)
结果同上
这里的主要问题是当写回那些圆圈时,你的 px
和 py
被调换了。你必须做 (py, px)
.
但是,此外,为了更快地找到红色像素(在我的机器上快 135 倍!),请结合使用
cv2.inRange
(生成二值mask图像,匹配像素为1,不匹配像素为0)np.argwhere
(其中 returns 值为非零的矩阵的索引)
import cv2
import numpy as np
img = cv2.imread("RvegM.png")
red_pixels = np.argwhere(cv2.inRange(img, (0, 0, 250), (0, 0, 255)))
for px, py in red_pixels:
cv2.circle(img, (py, px), 5, (0, 255, 255), 1)
cv2.imwrite("out.png", img)
out.png 最终看起来像这样: