2017-12-08 6 views
0

Ich arbeite an einem Projekt, um Bilder der Kacheln zu klicken und OpenCV zu verwenden, um herauszufinden, dass die Kachel besucht wird oder nicht.Python OpenCV - Versuche eine vollständig sichtbare Kachel zu identifizieren (alle vier Kanten sind sichtbar) und zeichne eine grüne Kontur Kanten

a green contour is shown on visit-able tile

unter Fliese Im Bild wird nicht besuchen-able -

Accessible Kachel sollte, wie unten gezeigt werden.

enter image description here

-Code i geschrieben haben, ist mehrere Konturen zu identifizieren.

import numpy as np 
import cv2 

image1 = cv2.imread('floor3.jpg')#, cv2.IMREAD_ANYCOLOR | cv2.IMREAD_ANYDEPTH) 
orig = image1.copy() 
cv2.imshow("Game Boy Screen", orig) 
cv2.waitKey(0) 

gray = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY) 
gray = cv2.bilateralFilter(gray, 11, 17, 17) 
edged = cv2.Canny(gray, 30, 200) 
flag, thresh = cv2.threshold(edged, 120, 255, cv2.THRESH_BINARY) 
im2, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 

try: hierarchy = hierarchy[0] 
except: hierarchy = [] 

height, width, _ = image1.shape 
min_x, min_y = width, height 
max_x = max_y = 0 

# computes the bounding box for the contour, and draws it on the frame, 
for contour, hier in zip(contours, hierarchy): 
    (x,y,w,h) = cv2.boundingRect(contour) 
    min_x, max_x = min(x, min_x), max(x+w, max_x) 
    min_y, max_y = min(y, min_y), max(y+h, max_y) 
    if w > 80 and h > 80: 
     cv2.rectangle(orig, (x,y), (x+w,y+h), (255, 0, 0), 2) 

if max_x - min_x > 0 and max_y - min_y > 0: 
    cv2.rectangle(orig, (min_x, min_y), (max_x, max_y), (255, 0, 0), 3) 

cv2.imshow("Game Boy Screen", orig) 
cv2.waitKey(0) 

Unten ist der Ausgang ich erhalte -

Instead of 1 contour as shown in first image i am getting multiple contours

Originalbild:

enter image description here

Antwort

1

Original-:

  • Zuerst sollten Sie auch Ihr Originalbild einfügen.
  • Zweitens, minAreaRect anders als boundingRect zu verwenden, um die gedrehten Rechtecke zu finden.

aktualisieren:

Ich glaube nicht tun findContours auf Canny Kanten eine Idee gut ist. Ich mache es einfach auf threshed binary image, dann entfernen Sie die Konturen mit kleinen Flächen. So können wir die Grenze von Regionen bekommen. Dann, um zu beurteilen, ob die Region abgeschlossen ist oder nicht, ist es bis zu Ihrem mathematischen Wissen.

enter image description here


#!/usr/bin/python3 
# 2017.12.09 00:25:47 CST 
# 2017.12.09 14:26:01 CST 
import cv2 
import numpy as np 

img = cv2.imread("test.jpg") 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
gray = cv2.bilateralFilter(gray, 11, 17, 17) 
th, threshed = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY) 
_, cnts, _ = cv2.findContours(threshed,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 

canvas = np.zeros_like(img, np.uint8) 
H,W = img.shape[:2] 
AREA = H*W 
for cnt in cnts: 
    area = cv2.contourArea(cnt) 
    if(area<AREA/100): 
     continue 
    _ = cv2.drawContours(canvas, [cnt], -1, (0,255,0), 1, cv2.LINE_AA) 


cv2.imwrite("result.png", canvas) 

Update 2: Nachdem die Konturen der Regionen erhalten, dann, wie zu beurteilen, ob es vollständig ist oder nicht?

Sie sollten definieren, was abgeschlossen ist? In dieser Situation, die komplette Kachel bedeutet, es ist ein Viereck, vier Eckpunkte, fast gleiche Längen der Seite. Dann programmieren Sie den Zustand, um dem Computer zu sagen, wie er zu urteilen hat. Es ist Ihre Aufgabe, Sie sollten zuerst versuchen, es selbst zu lösen. enter image description here

Gesamt Code und das Ergebnis:

#!/usr/bin/python3 
# 2017.12.09 00:25:47 CST 
# 2017.12.09 14:26:01 CST 
# 2017.12.09 17:52:17 CST 
import cv2 
import numpy as np 

## lambda: calc distance 
dist = lambda pt1, pt2: ((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)**0.5 

img = cv2.imread("img04.jpg") 

## (1) filter, threshed 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
gray = cv2.bilateralFilter(gray, 11, 17, 17) 
th, threshed = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY) 

## (2) findContours 
_, cnts, _ = cv2.findContours(threshed,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 


## (3) some variables 
H,W = img.shape[:2] 
AREA = H*W 
xcnts = [] 
R = 0.8 

## (4) judge wether the contour is belongs to a complete tile 
for cnt in cnts: 
    ## (4.1) filter by area 
    area = cv2.contourArea(cnt) 
    if(area<AREA/100): 
     continue 
    ## (4.2) calc arpprox contour 
    arclen = cv2.arcLength(cnt, closed=True) 
    approx = cv2.approxPolyDP(cnt, arclen*0.02, closed=True) 
    ## (4.3) filter by "complete ruler" 
    ## "the complete tile means it is a quadrilateral, four corner points, almost equal lengths of side" 
    pts = np.array(approx).reshape(-1,2) 
    if len(pts) == 4: 
     lens = np.array(list(dist(pts[i], pts[(i+1)%4]) for i in range(4))) 
     flag = True 
     for x in lens: 
      if not (R< x/lens[0] < 1.0/R): 
       flag = False 
       continue 
     if flag: 
      xcnts.append(cnt) 

## (5) draw and save 
res = img.copy() 
for cnt in xcnts: 
    cv2.drawContours(res, [cnt], -1, (0,255,0), -1, cv2.LINE_AA) 
cv2.imwrite("00result.png", res) 

enter image description here


Update 3 (Datum der letzten Aktualisierung):

ich den festen gedroschen Wert in der Verwendung mein code nur weil dein bild ein großes darlegt k Ursprung. Wie für dieses Bild

enter image description here,

gibt es keine große dunkle, so dass die Schwellen Flag auf cv2.THRESH_OTSU ändern und modifizieren, um AREA/20 oder größer ist, modifizieren, um die R kleiner wie der Bereich R=0.7 dreschen.

Dann bekomme ich das Ergebnis:

enter image description here


ähnliche Fragen:

(1) Image processing using opencv and python

(2) Python OpenCV - Trying to identify a completely visible tile (all four edges are visible) and draw a green contour edges

+0

Dank für Ihre Antwort. Ich habe das Originalbild hinzugefügt. –

+0

bei der Verwendung von BoundingRect wie vorgeschlagen, bekomme ich folgenden Fehler - (x, y, w, h) = cv2.minAreaRect (Kontur) ValueError: nicht genug Werte zu entpacken (erwartet 4, bekam 3) –

+0

@Ankit ich testen mit Ihr Originalbild, und es ist nicht einfach, es zu erkennen. Und ich habe eine Frage in deinem Code gefunden. Nach der Erkennung "Canny Kanten" können wir die Kanten finden, aber die Kanten sind nicht kontinuierlich und geschlossen. Wenn wir also "FindContours" finden, finden wir die Konturen der diskontinuierlichen und offenen Kanten, nicht der Regionen. (Normalerweise finde ichContours auf gedroschenem Binärbild). Und in Ihrem Bild wurde das Rechteck in eine Raute umgewandelt, also auch das 'cv2.minAreaRect' (zur Erkennung eines gedrehten Rechtecks,' (x1, y2), (x2, y2), Winkel = cv2.minAreaRect (pts) ') wird ungültig. – Silencer

Verwandte Themen