Найти координаты красного пикселя на изображении - PullRequest
1 голос
/ 28 апреля 2020

Входное изображение

Изображение выше - пример ввода, который я беру, и я хочу найти координаты всех красных пикселей на этом изображении и сохранить его в списке, а затем позже, итерируйте этот список и обведите круги вокруг каждой из координат, которые мы нашли выше на изображении, используя функцию 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)

Но выполнение вышеизложенного не делает круг по всем координатам. Я думаю, что что-то не так с хранением координат и доступом к ним. Может кто-нибудь указать на ошибку и помочь мне, пожалуйста.

Я получаю следующий вывод, который не верен

Ответы [ 3 ]

2 голосов
/ 28 апреля 2020

Вы будете там весь день с for петлями! Вы были бы на много миль быстрее, чтобы сделать морфологическую свертку с кольцевым ядром. Я могу показать вам, как это сделать быстро в ImageMagick , но вы можете сделать то же самое с OpenCV .

Вот команда basi c:

magick stars.png -morphology convolve ring:3.5,4.5 result.png

enter image description here

Я запусту его снова и на этот раз, попросите 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

Существует превосходное описание увлекательной темы морфологии и того, как она работы Энтони Тиссена здесь .


Вот версия 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)

Результаты те же, что и выше .

2 голосов
/ 28 апреля 2020

Основная проблема здесь в том, что при записи этих кругов ваши px и py транспонируются. Вам нужно будет сделать (py, px).

Но, кроме того, чтобы значительно быстрее находить красные пиксели ( 135 раз быстрее на моей машине!), Используйте комбинацию

  • cv2.inRange (который генерирует двоичное изображение маски, где совпадающие пиксели равны 1, а несовпадающие равны 0)
  • np.argwhere (который возвращает индексы матрицы, где значение не равно нулю)
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 в конечном итоге выглядит так:

enter image description here

1 голос
/ 28 апреля 2020

Ваши условия плохо написаны. Прежде всего, лучше искать в диапазоне, если значение пикселя <10, мы можем считать его черным. </p>

Для красного мы можем проверить, имеют ли каналы 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...