webentwicklung-frage-antwort-db.com.de

Wie extrahiere ich einen bestimmten Abschnitt eines Bildes mit OpenCV in Python?

Ich versuche, einen Teil eines Bildes durch Ausführen der Canny Edge-Erkennung zu extrahieren. Ich habe erfolgreich eine Maske dieses Objekts erstellt. Wenn ich jedoch eine bitwise_and-Operation mit dem Originalbild durchführe, um den Vordergrundabschnitt zu extrahieren, wird der folgende Fehler angezeigt.

OpenCV Error: Assertion failed ((mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1)) in cv::binary_op, file C:\projects\opencv-python\opencv\modules\core\src\arithm.cpp, line 241
    Traceback (most recent call last):
      File "C:\Users\Boudhayan Dev\Desktop\extraction.py", line 37, in <module>
        new_image = cv2.bitwise_and(img_rgb,img_rgb,mask=mask)
    cv2.error: C:\projects\opencv-python\opencv\modules\core\src\arithm.cpp:241: error: (-215) (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1) in function cv::binary_op

Mein Code ist wie folgt -

import cv2
import numpy as np

img_rgb = cv2.imread("3.jpg")
cv2.namedWindow("Original Image",cv2.WINDOW_NORMAL)

img = cv2.cvtColor(img_rgb,cv2.COLOR_RGB2HSV)
img = cv2.bilateralFilter(img,9,105,105)
r,g,b=cv2.split(img)
equalize1= cv2.equalizeHist(r)
equalize2= cv2.equalizeHist(g)
equalize3= cv2.equalizeHist(b)
equalize=cv2.merge((r,g,b))

equalize = cv2.cvtColor(equalize,cv2.COLOR_RGB2GRAY)

ret,thresh_image = cv2.threshold(equalize,0,255,cv2.THRESH_OTSU+cv2.THRESH_BINARY)
equalize= cv2.equalizeHist(thresh_image)


canny_image = cv2.Canny(equalize,250,255)
canny_image = cv2.convertScaleAbs(canny_image)
kernel = np.ones((3,3), np.uint8)
dilated_image = cv2.dilate(canny_image,kernel,iterations=1)


new,contours, hierarchy = cv2.findContours(dilated_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours= sorted(contours, key = cv2.contourArea, reverse = True)[:10]
c=contours[0]
print(cv2.contourArea(c))
final = cv2.drawContours(img, [c], -1, (255,0, 0), 3)



mask = np.zeros(img_rgb.shape,np.uint8)
new_image = cv2.drawContours(mask,[c],0,255,-1,)
new_image = cv2.bitwise_and(img_rgb,img_rgb,mask=mask)


cv2.namedWindow("new",cv2.WINDOW_NORMAL)
cv2.imshow("new",new_image)

cv2.imshow("Original Image",img)
cv2.waitKey() 

HINWEIS: - Der Code funktioniert einwandfrei, wenn ich versuche, den bitwise_and mit einer Graustufenversion des Bildes auszuführen. RGB, HSV oder andere Farbräume führen jedoch zu dem obigen Fehler.

Bitte helfen Sie.


EDIT 1 - Das fragliche Bild ist dieses -

 3.jpeg

EDIT 2-

Das Folgende ist das Ergebnis nach Verwendung der Numpy-Methode. Wie Sie sehen, hat das extrahierte Bild dieselbe Größe wie die Orange, enthält jedoch nicht die Orange, sondern die Maske selbst.

 result

EDIT 3- @ DanMašek und @lightalchemist, ich konnte endlich jedes Vordergrundbild extrahieren.

 result1

 result2

Vielen Dank

5
Boudhayan Dev

Ich habe den oben angegebenen Code verwendet, aber nur die Zeile geändert, in der cv2.bitwise_and() verwendet wird:

new_image = cv2.bitwise_and(img_rgb, img_rgb, mask = equalize)

Das ist was ich bekommen habe und was Sie erwartet haben (denke ich):

 enter image description here

EDIT

Ich verstehe es, Sie möchten Ihr Bild mit einem Bild mit der größten Fläche überdecken. Im folgenden zusätzlichen Ausschnitt habe ich das Bild digitalisiert, das die Kontur des größten Bereichs enthält, der als Maske verwendet werden soll.

new_image = cv2.drawContours(mask,[c], -1, (255,255,255), -1)
new_image_gray = cv2.cvtColor(new_image, cv2.COLOR_BGR2GRAY)
ret, thresh1 = cv2.threshold(new_image_gray, 100, 255, cv2.THRESH_BINARY)
final = cv2.bitwise_and(img_rgb, img_rgb, mask = thresh1)

Das habe ich bekommen:

 enter image description here

Verglichen mit dem Bild oben sehen Sie diese Löcher nicht innerhalb des interessierenden Objekts.

1
Jeru Luke

Der Fehler besagt, dass Sie versuchen, die bitwise_and -Operation für Matrizen auszuführen, bei denen die Einträge keine Ganzzahlen sind. Ich glaube, dass die Matrizen auch die gleiche Anzahl von Kanälen haben müssen. Deshalb funktioniert es mit Ihrem Graustufenbild, nicht jedoch mit dem HSV-Bild.

Anstatt bitwise_and zu verwenden, ist es einfacher und flexibler, die Matrixvektorisierung einfach zu verwenden, um die Maskierung wie folgt auszuführen:

mask = np.zeros_like(img_rgb, dtype=np.uint8)

# I believe you want to draw the filled in contour on the mask
# You code actually assigns the resulting mask to new_image
# But that does not affect things as drawContours modifies mask in place
mask = cv2.drawContours(mask, [c] ,0, 255, -1) 

new_image = img_rgb.copy()
new_image[mask < 255] = 0  # Set values not masked to be 0

Wenn Ihre Maske eine Einkanalmatrix anstelle einer 3-Kanalmatrix ist, müssen Sie den Code entsprechend ändern

new_image[mask < 255, :] = 0

1
lightalchemist