python3+opencv3識別圖片中的物體並截取

運行環境:python3.6.4
         opencv3.4.0

# -*- coding:utf-8 -*-
 
"""
Note: 使用Python和OpenCV檢測圖像中的物體並將物體裁剪下來
"""
 
import cv2
import numpy as np
 
 
# step1:加載圖片,轉成灰度圖
image = cv2.imread("353.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 
# step2:用Sobel算子計算x,y方向上的梯度,之後在x方向上減去y方向上的梯度,通過這個減法,我們留下具有高水平梯度和低垂直梯度的圖像區域。
gradX = cv2.Sobel(gray, cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(gray, cv2.CV_32F, dx=0, dy=1, ksize=-1)
 
# subtract the y-gradient from the x-gradient
gradient = cv2.subtract(gradX, gradY)
gradient = cv2.convertScaleAbs(gradient)
# show image
cv2.imshow("first", gradient)
cv2.waitKey()
 
# step3:去除圖像上的噪聲。首先使用低通濾潑器平滑圖像(9 x 9內核),這將有助於平滑圖像中的高頻噪聲。
# 低通濾波器的目標是降低圖像的變化率。如將每個像素替換爲該像素周圍像素的均值。這樣就可以平滑並替代那些強度變化明顯的區域。
# 然後,對模糊圖像二值化。梯度圖像中不大於90的任何像素都設置爲0(黑色)。 否則,像素設置爲255(白色)。
# blur and threshold the image
blurred = cv2.blur(gradient, (99))
_, thresh = cv2.threshold(blurred, 90255, cv2.THRESH_BINARY)
# SHOW IMAGE
cv2.imshow("thresh", thresh)
cv2.waitKey()
 
# step4:在上圖中我們看到蜜蜂身體區域有很多黑色的空餘,我們要用白色填充這些空餘,使得後面的程序更容易識別昆蟲區域,
# 這需要做一些形態學方面的操作。
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2525))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# show image
cv2.imshow("closed1", closed)
cv2.waitKey()
 
# step5:從上圖我們發現圖像上還有一些小的白色斑點,這會干擾之後的昆蟲輪廓的檢測,要把它們去掉。分別執行4次形態學腐蝕與膨脹。
# perform a series of erosions and dilations
closed = cv2.erode(closed, None, iterations=4)
closed = cv2.dilate(closed, None, iterations=4)
# show image
cv2.imshow("closed2", closed)
cv2.waitKey()
 
# step6:找出昆蟲區域的輪廓。
# cv2.findContours()函數
# 第一個參數是要檢索的圖片,必須是爲二值圖,即黑白的(不是灰度圖),
# 所以讀取的圖像要先轉成灰度的,再轉成二值圖,我們在第三步用cv2.threshold()函數已經得到了二值圖。
# 第二個參數表示輪廓的檢索模式,有四種:
# 1. cv2.RETR_EXTERNAL表示只檢測外輪廓
# 2. cv2.RETR_LIST檢測的輪廓不建立等級關係
# 3. cv2.RETR_CCOMP建立兩個等級的輪廓,上面的一層爲外邊界,裏面的一層爲內孔的邊界信息。如果內孔內還有一個連通物體,這個物體的邊界也在頂層。
# 4. cv2.RETR_TREE建立一個等級樹結構的輪廓。
# 第三個參數爲輪廓的近似方法
# cv2.CHAIN_APPROX_NONE存儲所有的輪廓點,相鄰的兩個點的像素位置差不超過1,即max(abs(x1-x2),abs(y2-y1))==1
# cv2.CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點座標,例如一個矩形輪廓只需4個點來保存輪廓信息
 
# cv2.findContours()函數返回兩個值,一個是輪廓本身,還有一個是每條輪廓對應的屬性。
# cv2.findContours()函數返回第一個值是list,list中每個元素都是圖像中的一個輪廓,用numpy中的ndarray表示。
# 每一個ndarray裏保存的是輪廓上的各個點的座標。我們把list排序,點最多的那個輪廓就是我們要找的昆蟲的輪廓。
= cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# import pdb
# pdb.set_trace()
_a, cnts, _b = x
= sorted(cnts, key=cv2.contourArea, reverse=True)[0]
 
# OpenCV中通過cv2.drawContours在圖像上繪製輪廓。
# 第一個參數是指明在哪幅圖像上繪製輪廓
# 第二個參數是輪廓本身,在Python中是一個list
# 第三個參數指定繪製輪廓list中的哪條輪廓,如果是-1,則繪製其中的所有輪廓
# 第四個參數是輪廓線條的顏色
# 第五個參數是輪廓線條的粗細
 
# cv2.minAreaRect()函數:
# 主要求得包含點集最小面積的矩形,這個矩形是可以有偏轉角度的,可以與圖像的邊界不平行。
# compute the rotated bounding box of the largest contour
rect = cv2.minAreaRect(c)
# rect = cv2.minAreaRect(cnts[1])
box = np.int0(cv2.boxPoints(rect))
 
 
# draw a bounding box arounded the detected barcode and display the image
cv2.drawContours(image, [box], -1, (02550), 3)
cv2.imshow("Image", image)
cv2.imwrite("contoursImage2.jpg", image)
cv2.waitKey(0)
 
# step7:裁剪。box裏保存的是綠色矩形區域四個頂點的座標。我將按下圖紅色矩形所示裁剪昆蟲圖像。
# 找出四個頂點的x,y座標的最大最小值。新圖像的高=maxY-minY,寬=maxX-minX。
Xs = [i[0for in box]
Ys = [i[1for in box]
x1 = min(Xs)
x2 = max(Xs)
y1 = min(Ys)
y2 = max(Ys)
hight = y2 - y1
width = x2 - x1
cropImg = image[y1:y1+hight, x1:x1+width]
 
# show image
cv2.imshow("cropImg", cropImg)
cv2.imwrite("bee.jpg", cropImg)
cv2.waitKey()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章