Kürzlich habe ich im Unterricht die Bildverarbeitung gelernt und die Technik der Transformation einer Ebene durch Matrixtransformation gelernt.
Dann bekam ich plötzlich den Drang, Pisas schrägen Turm vertikal zu machen, also werde ich versuchen, Python und OpenCV zu üben.
Nun, ich kann es kaum verstehen, also bin ich ein Huckepack-Fahrer mit den nützlichen Funktionen von OpenCV.
Lassen Sie uns vertikal!
windows10 Python 3.7.7 OpenCV 3.4.2 Pillow 7.1.2 numpy 1.18.4
Klicken Sie hier, um den diagonalen Turm von Pisa zu verwenden
Da Weiß insgesamt stark ist, werde ich diesmal versuchen, den Umriss anhand des Farbtons anstelle der Kante zu erkennen (Ganz zu schweigen von dem Hintergrund, der am Rand nicht funktioniert hat)
pisa
#Weißerkennung
def detect_white_color(img):
#In HSV-Farbraum konvertieren
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
#Weißer HSV-Wertebereich
hsv_min = np.array([0,0,100])
hsv_max = np.array([180,45,255])
mask = cv2.inRange(hsv, hsv_min, hsv_max)
#Maskierungsprozess
masked_img = cv2.bitwise_and(img, img, mask=mask)
return mask, masked_img
Die linke ist mask und die rechte ist masked_img
Als nächstes binarisieren und erkennen Sie das Rechteck
pisa
imgray = cv2.cvtColor(blurred_img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,115,255,0)
im, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0,255,0), 2)
Führen Sie zuerst minAreaRect (Konturen) auf rect aus minAreaRect () gibt einen Taple mit einer Box2D-Struktur zurück Die Struktur von Box2D ist (oberer linker Punkt (x, y), horizontale und vertikale Größe (Breite, Höhe), Drehwinkel).
Um ein Rechteck zu zeichnen, müssen wir diese Informationen in vier Koordinaten konvertieren. Führen Sie also boxPoints () aus, die dies können.
Es ist ein Fluss, der am Ende gezeichnet werden muss (Referenz Referenz)
Es scheint zu funktionieren, aber ich werde es mit einem Gaußschen Filter verwischen, nur für den Fall, dass es andere Fotos gut verarbeiten kann!
pisa
#Mit Gauß-Filter verwischen
blurred_img = cv2.GaussianBlur(white_masked_img,(5,5),10)
Die Kante hat sich ziemlich beruhigt
Nur das größte Rechteck reicht aus, um es aufzunehmen
pisa
#Eine Funktion, die den Index des Rechtecks mit der größten Fläche zurückgibt
def detect_max_rect(img,contours):
#Index der Konturen, die die maximale Fläche einnehmen
max_idx = 0
for i in range(len(contours)):
if cv2.contourArea(contours[max_idx]) < cv2.contourArea(contours[i]):
max_idx = i
return max_idx
Unter [contourArea (contours)](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html#contour- Sie können den Bereich des Platzes von den Ecken umgeben bekommen
Verwenden Sie diese Option, um eine Funktion zu definieren, die den Index der Koordinaten zurückgibt, die den Bereich maximieren
Durch Festlegen von minAreaRect (max_idx) kann nur das Quadrat mit der maximalen Fläche extrahiert werden.
Du lehnst dich!
Let's Vertical
Es tut mir leid, dass ich es mache, ohne ein Flussdiagramm zu schreiben
Erstellen Sie zunächst eine Funktion zum Trimmen des quadratischen Bereichs, den Sie später möglicherweise benötigen.
pisa
#Ausschaltfunktion
def crop_rect(img, rect):
center, size, angle = rect
center = tuple(map(int, center)) # float -> int
size = tuple(map(int, size)) # float -> int
h, w = img.shape[:2] #Bildhöhe und -breite
#Holen Sie sich Höhe und Breite von Rect
height,width=rect[1]
height,width=int(height),int(width)
#Da der Winkel den durch die horizontale Linie gebildeten Winkel angibt,+90
if angle<0:
angle+=90
#Drehen Sie das Bild mit der affinen Matrix
M = cv2.getRotationMatrix2D(center, angle, 1)
rotated = cv2.warpAffine(img, M, (w, h))
#ausgeschnitten
cropped = cv2.getRectSubPix(rotated, (w,h), center)
return cropped
Ich habe die Details in den Kommentaren geschrieben Das Bild des Ausführungsergebnisses ist wie folgt
Es ist unnatürlich und interessant
Es ist einfach, weil der Winkel erhalten wird.
Erstellen Sie eine Funktion zum Drehen des Bildes
pisa
#Funktion zum Drehen
def rotate_img(img,rect):
#Berechnen Sie die Bildschirmmitte aus Höhe und Breite
_height = img.shape[0]
_width = img.shape[1]
_center = (int(_width/2), int(_height/2))
_angle=rect[2]
#Da der Winkel den durch die horizontale Linie gebildeten Winkel angibt, beträgt er +90.
if _angle<0:
_angle+=90
#Drehen Sie das Bild mit der affinen Matrix
_M = cv2.getRotationMatrix2D(_center, _angle, 1)
_rotated_img = cv2.warpAffine(img, _M, (_width, _height))
return _rotated_img
Nehmen Sie die Bildmitte und drehen Sie sie um den Winkel von Pisa.
Hoch perfekt! !! !!
.. .. .. Ich mache Witze, es tut mir leid Bitte werfen Sie die vorherige Funktion weg
Als Richtlinie werde ich den ausgehöhlten Teil aus dem Originalbild ergänzen und das zugeschnittene Bild an denselben Koordinaten einfügen.
pisa
#Bildkomplement
def inpaint_img(img):
_mask = cv2.imread('img/pisa1.jpg')
#Mit Weiß füllen
cv2.drawContours(_mask, [box], 0, (255,255,255), -1)
_maskGray = cv2.cvtColor(_mask,cv2.COLOR_BGR2GRAY)
ret,_thresh = cv2.threshold(_maskGray,254,255,0)
#Bildkorrektur
dst = cv2.inpaint(img, _thresh, 3, cv2.INPAINT_TELEA)
cv2.imwrite('img/pisa_rect_inpaint.jpg', dst)
inpaint ist das Eingabebild und ein Maskenbild derselben Größe. Wird benötigt Pixel mit Werten ungleich Null in diesem Maskenbild geben an, wo repariert werden muss Mit anderen Worten, es kann ergänzt werden, indem das zu reparierende Teil weiß und der Rest schwarz gemacht wird.
Es gibt zwei Arten von Algorithmen, INPAINT_TELEA und INPAINT_NS, und dieses Mal habe ich versucht, beide auszuführen.
Links INPAINT_TELEA und rechts INPAINT_NS
Ich habe das Gefühl, dass der leere Teil von NS etwas sauberer ist, deshalb habe ich diesen dieses Mal übernommen
Verwenden der Pillow-Bibliothek, da das Einfügen von Bildern nur mit OpenCV problematisch zu sein scheint
pisa
#Fügen Sie die zugeschnittene Pisa in das ergänzende Hintergrundbild ein
def paste_pisa(rect):
#x,Die Mittelkoordinaten des getrimmten Pisa werden in y eingegeben
x,y=rect[0]
#Ich möchte es nach links oben bringen, also die Hälfte der Breite w und Höhe h x,Von y subtrahieren
_w,_h=rect[1]
#print(h,w)
x -= _h/2
y -= _w/2
x,y=int(x),int(y)
source_img = Image.open('img/pisa_rect_crop.jpg')
canvas_img = Image.open('img/pisa_rect_inpaint.jpg')
#Fügen Sie zugeschnittenes Pisa auf das bemalte Bild ein
canvas_img.paste(source_img, (x,y))
#Bild speichern
canvas_img.save('img/vertical_pisa.jpg')
Ausführen
** Pi, Pi, Pisa stand auf! !! !! ** ** **
Der komplementäre Teil ist sichtbar und rau und nicht sehr vertikal, aber insgesamt habe ich das Gefühl, dass ich es gut gesagt habe.
Persönlich war ich überrascht über die Genauigkeit der Inpaint-Funktion nur für den Algorithmus ohne jegliches Lernen. Auch die dynamische Eingabe von Python ist zu bequem und eine perfekte Phrase. .. .. Ehrlich gesagt verstehe ich nicht, aber ich bin beeindruckt von den entspannten Spezifikationen, weil es Orte gibt, an denen ich vorgegangen bin
Dieses Mal wird der Bereich anhand der Farbe erkannt. Wenn Sie dies also beim nächsten Mal mit der Kante tun können, wird der Freiheitsgrad meiner Meinung nach zunehmen.
Jeder, ** Let'vertical! ** ** **
Das ist normale Schwerkraft
minAreaRect-Funktion https://www.it-swarm.dev/ja/python/minarearect-opencv%E3%81%AB%E3%82%88%E3%81%A3%E3%81%A6%E8%BF%94%E3%81%95%E3%82%8C%E3%82%8B%E5%9B%9B%E8%A7%92%E5%BD%A2%E3%81%AE%E3%83%88%E3%83%AA%E3%83%9F%E3%83%B3%E3%82%B0python/824441051/
Konturextraktion https://hk29.hatenablog.jp/entry/2020/02/01/162533
Weiße Extraktion https://temari.co.jp/blog/2017/11/13/opencv-4/
Trimmen https://teratail.com/questions/219340
Inpaint-Funktion https://lp-tech.net/articles/kb4bO/view?page=2
Kissenbibliothek https://water2litter.net/rum/post/python_pil_paste/
Recommended Posts