Обнаружение квадратов/прямоугольников с использованием OpenCV

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

Я написал код, но он не работает.

import numpy as np 
import cv2 
 
img = cv2.imread('gulRec.jpg') 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

 
imagem = (255-gray)
ret,thresh = cv2.threshold(imagem,120,200,1) 
 
contours,h = cv2.findContours(thresh,1,2)

for cnt in contours: 
    approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True) 
    print (len(approx))
    if len(approx)==4: 
        cv2.drawContours(img,[cnt],0,(0,0,255),-1) 
        
cv2.imshow('thresh',thresh)  
cv2.imshow('img',img) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 

picture 1 Изображение 2


person Mads    schedule 23.11.2020    source источник
comment
Вы пробовали другой метод, такой как адаптивное определение порога или сегментация на основе пирамиды?   -  person Dr Yuan Shenghai    schedule 23.11.2020
comment
Неа? что это?   -  person Mads    schedule 23.11.2020
comment
попробуйте немного Canny Edge и shi-tomasi (goodFeaturesToTrack(), если я правильно помню)   -  person Daemon Painter    schedule 23.11.2020
comment
Вы можете использовать в своем методе функции контура. Как выбор порога для области.   -  person Burak    schedule 23.11.2020
comment
Но перед этим вам нужно иметь лучшее бинарное изображение. Канни - хороший вариант. Также обратите внимание на морфологические операции, особенно открытие.   -  person Burak    schedule 23.11.2020
comment
Используйте cv2.inRange() для порога на желтом, а затем отдельно на красном. Затем используйте морфологию для очистки каждого. Затем совместите пороги. Затем получите контуры из порогового изображения. Отфильтруйте контуры по площади, чтобы получить только большие.   -  person fmw42    schedule 23.11.2020


Ответы (1)


Вот один из способов обнаружения красных и желтых кубов в Python/OpenCV. Основная идея для красных и желтых кубов состоит в том, чтобы признать, что оттенок красного и желтого — самый низкий из всех цветов. Таким образом, можно преобразовать в HSV и использовать cv2.inRange() для порогового значения красного и желтого.

Вход:

введите здесь описание изображения

import cv2
import numpy as np

img = cv2.imread("4cubes.jpg")

# convert to HSV, since red and yellow are the lowest hue colors and come before green
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# create a binary thresholded image on hue between red and yellow
lower = (0,240,160)
upper = (30,255,255)
thresh = cv2.inRange(hsv, lower, upper)

# apply morphology
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9,9))
clean = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15,15))
clean = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

# get external contours
contours = cv2.findContours(clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]

result1 = img.copy()
result2 = img.copy()
for c in contours:
    cv2.drawContours(result1,[c],0,(0,0,0),2)
    # get rotated rectangle from contour
    rot_rect = cv2.minAreaRect(c)
    box = cv2.boxPoints(rot_rect)
    box = np.int0(box)
    # draw rotated rectangle on copy of img
    cv2.drawContours(result2,[box],0,(0,0,0),2)

# save result
cv2.imwrite("4cubes_thresh.jpg",thresh)
cv2.imwrite("4cubes_clean.jpg",clean)
cv2.imwrite("4cubes_result1.png",result1)
cv2.imwrite("4cubes_result2.png",result2)

# display result
cv2.imshow("thresh", thresh)
cv2.imshow("clean", clean)
cv2.imshow("result1", result1)
cv2.imshow("result2", result2)
cv2.waitKey(0)
cv2.destroyAllWindows()

Пороговое изображение:

введите здесь описание изображения

Морфологически очищенное изображение:

введите здесь описание изображения

Контуры:

введите здесь описание изображения

Повернутые ограничивающие рамки:

введите здесь описание изображения

person fmw42    schedule 23.11.2020