Kantenerkennung mit Canny-Algorithmus! Problem bei den Ecken

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
kl.feigling89
User
Beiträge: 42
Registriert: Montag 24. Februar 2014, 14:47

Hallo, ich habe ein sehr großes Problem. Ich möchte die Kanten eines Bildes detektieren und benutze dafür den Canny-Algorithmus der OpenCV Library. Leider verursacht der Algorithmus ein paar Fehler:
Bei einem Rechteck werden die beiden linken Randpixel nicht gezeichnet.

Code: Alles auswählen

def getEdgeImage(image,threshold1,threshold2):
	edgeImage = cv2.Canny(image,threshold1,threshold2)
	return edgeImage
Hier einmal ein kleines beispiel: x soll das Rechteck darstellen und 0 der Hintergrund

Originalbild

Code: Alles auswählen

00000000000
00000000000
000xxxxxx000
000xxxxxx000
000xxxxxx000
00000000000
So solte es aussehen :

Code: Alles auswählen

000000000000
00xxxxxxxx000
00x00000x000
00x00000x000
00x00000x000
00xxxxxxxx000
Bei mir sieht es aber so aus:

Code: Alles auswählen

000000000000
000xxxxxxx000
00x00000x000
00x00000x000
00x00000x000
000xxxxxxx000
Habe ich was falsch gemacht? oder kann der Canny-Algorithmus die Ecke nicht sauber ? oder gibt es noch eine alternative?

Hoffe ihr könnt mir Helfen....
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

Wie wär's mit echten Beispielen und echten Bildern?

OpenCV hat auch noch den Sobel Operator und den LaPlace Filter implementiert.
kl.feigling89
User
Beiträge: 42
Registriert: Montag 24. Februar 2014, 14:47

So hier ein Beispiel:

Das Original Bild:
Bild
Hier nochmal eine vergrößerung:
Bild
und hier die Kante:
Bild

Deutlich zuerkennen das es nicht richtig passt.

Threshold1 =1
Threshold2 =255
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Zeig doch mal deinen Beispielcode! Das wäre für mich die offensichtliche Fehlerquelle.

Grüße,
anogayales
kl.feigling89
User
Beiträge: 42
Registriert: Montag 24. Februar 2014, 14:47

Also ich habe folgenden Code:

Code: Alles auswählen

import cv2

threshold1 = 1
threshold2 = 255
path = 'test88.bmp'
image = cv2.imread(path,-1)
b,g,r = cv2.split(image)
edgeImage = cv2.Canny(b,threshold1,threshold2)
cv2.imwrite('edgeImage.png',edgeImage)
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

War mir vorher auch nicht bewusst, aber der Canny Filter hat ein Problem mit "perfekten" Kanten zumindest wenn es es sich im Pixel bereich anschaut. Für die Bildverarbeitung von Kameras spielt das allerdings keine Rolle.

Hier ein Beispiel:

Code: Alles auswählen

import cv2
import numpy as np

#the image
img = np.ones([10,10])
img[3:7, 3:7] = 255
print "Image:"
print img

blur_img = cv2.GaussianBlur(img, (3,3), 0)
print
print "Blur:"
print blur_img.astype(np.int)

detected_edges = cv2.Canny(img.astype(np.uint8), 0, 0)
print
print "Canny without blur:"
print detected_edges.astype(np.int)

detected_edges = cv2.Canny(blur_img.astype(np.uint8), 0, 0)
print
print "Canny with blur:"
print detected_edges.astype(np.int)

from scipy import ndimage
sx = ndimage.sobel(img, axis=0, mode='constant')
sy = ndimage.sobel(img, axis=1, mode='constant')
sob = np.hypot(sx, sy)
print
print "Sobel:"
print sob.astype(np.int)
Output:

Code: Alles auswählen

Image:
[[   1.    1.    1.    1.    1.    1.    1.    1.    1.    1.]
 [   1.    1.    1.    1.    1.    1.    1.    1.    1.    1.]
 [   1.    1.    1.    1.    1.    1.    1.    1.    1.    1.]
 [   1.    1.    1.  255.  255.  255.  255.    1.    1.    1.]
 [   1.    1.    1.  255.  255.  255.  255.    1.    1.    1.]
 [   1.    1.    1.  255.  255.  255.  255.    1.    1.    1.]
 [   1.    1.    1.  255.  255.  255.  255.    1.    1.    1.]
 [   1.    1.    1.    1.    1.    1.    1.    1.    1.    1.]
 [   1.    1.    1.    1.    1.    1.    1.    1.    1.    1.]
 [   1.    1.    1.    1.    1.    1.    1.    1.    1.    1.]]

Blur:
[[  1   1   1   1   1   1   1   1   1   1]
 [  1   1   1   1   1   1   1   1   1   1]
 [  1   1  16  48  64  64  48  16   1   1]
 [  1   1  48 143 191 191 143  48   1   1]
 [  1   1  64 191 255 255 191  64   1   1]
 [  1   1  64 191 255 255 191  64   1   1]
 [  1   1  48 143 191 191 143  48   1   1]
 [  1   1  16  48  64  64  48  16   1   1]
 [  1   1   1   1   1   1   1   1   1   1]
 [  1   1   1   1   1   1   1   1   1   1]]

Canny without blur:
[[  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0 255 255   0   0   0   0]
 [  0   0   0 255   0   0 255   0   0   0]
 [  0   0 255   0   0   0 255   0   0   0]
 [  0   0 255   0   0   0 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]

Canny with blur:
[[  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0 255   0   0 255   0   0   0]
 [  0   0   0 255   0   0 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]

Sobel:
[[   4    4    4    4    4    4    4    4    4    4]
 [   4    0    0    0    0    0    0    0    0    4]
 [   4    0  359  803 1016 1016  803  359    0    4]
 [   4    0  803 1077 1016 1016 1077  803    0    4]
 [   4    0 1016 1016    0    0 1016 1016    0    4]
 [   4    0 1016 1016    0    0 1016 1016    0    4]
 [   4    0  803 1077 1016 1016 1077  803    0    4]
 [   4    0  359  803 1016 1016  803  359    0    4]
 [   4    0    0    0    0    0    0    0    0    4]
 [   4    4    4    4    4    4    4    4    4    4]]
kl.feigling89
User
Beiträge: 42
Registriert: Montag 24. Februar 2014, 14:47

Danke für deine Hilfe, leider weiß ich immer noch nicht genau wie ich mein Problem der Kantenerkennung am besten lösen kann. Wenn ich dein Verfahren mit dem Weichzeichnen benutze kann es zu fehlern kommen, wenn sich das Objekt zu nah am Rand des Bildes befindet. Gibt es noch eine andere Lösung die dieses Problem nicht hat? oder kann man das noch mit einem Trick lösen?

Code: Alles auswählen

import cv2
import numpy as np
#the image
img = np.zeros([8,8])
img[3:7, 3:7] = 255
print "Image:"
print img
 
blur_img = cv2.GaussianBlur(img, (3,3), 0)
print
print "Blur:"
print blur_img.astype(np.int)
 
detected_edges = cv2.Canny(img.astype(np.uint8), 0, 0)
print
print "Canny without blur:"
print detected_edges.astype(np.int)
 
detected_edges = cv2.Canny(blur_img.astype(np.uint8), 0, 0)
print
print "Canny with blur:"
print detected_edges.astype(np.int)
Ausgabe mit Fehler:
Bild
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

Auch das ist wieder etwas was einen bei Bildern mit hohen Auflösungen und dem "wichtigen" in der Mitte nicht interessiert. Falls du ein einheitlichen Hintergrund hast kannst du deine Bildfläche um diesen Erweitern.

Möglicherweise (wahrscheinlich) gibt es dafür eine Numpy Funktion, allerdings kenne ich keine und habe gerade keine Lust zum suchen aber das köntnest du in etwa so machen:

Code: Alles auswählen

import numpy as np

img = np.zeros([8,8])
img[3:7, 3:7] = 255

bigger_img = np.zeros([10,10])
bigger_img[:,:] = 5  # beispiel hintergrund farbe

bigger_img[1:9, 1:9] = img #einfuegen des original bilds
Für nicht einheitliche Hintergründe fällt mir keine Lösung ein.
Antworten