段力輝版本《OpenCV-Python 中文教程》學習


        此書極好,值得借鑒學習,並且開源開放。Python在實現過程中,體現出來了非常強的優勢,特別是結合Numpy來進行矩陣計算,有很多簡化方法。這里將學習過程代碼進行增編、添加后進行展示。

  Python目前的缺點應該是缺乏一個像ImageWatch這樣的工具,這將影響算法研究;另外Numpy的過度抽象,某種程度上也會造成障礙。

1、尋找指定色彩區域
Python的特色,在於Numpy的使用
import cv2
import numpy  as np

src = cv2.imread( "e:/template/tiantan.jpg")
hsv = cv2.cvtColor(src,cv2.COLOR_BGR2HSV)
lower_blue = np.array([ 100, 43, 46])
upper_blue = np.array([ 124, 255, 255])
mask = cv2.inRange(hsv,lower_blue,upper_blue)
res = cv2.bitwise_and(src,src,mask=mask)
cv2.imshow( "hsv",hsv)
cv2.imshow( "mask",mask)
cv2.imshow( "res",res)

cv2.waitKey( 0)
2、warpperspective 透視變化的python實現
import cv2
import numpy  as np

src = cv2.imread( "e:/template/steel03.jpg")
rows,cols,ch = src.shape
pts1 = np.float32([[ 122, 0],[ 814, 0],[ 22, 540],[ 910, 540]])
pts2 = np.float32([[ 0, 0],[ 960, 0],[ 0, 540],[ 960, 540]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(src,M,(cols,rows))

cv2.imshow( "src",dst)
cv2.waitKey( 0)
這里操作的核心,是一個np的矩陣。在C++中,使用Vector,可能會造成很多浪費。
3、自適應閾值
import cv2
import numpy  as np
 
obj = cv2.imread( "e:/template/pig.jpg", 0)
ret,th1 = cv2.threshold(obj, 100, 255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(obj, 255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 11, 2)
ret3,th3 = cv2.threshold(obj, 0, 255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow( "th3",th3)
print(ret3)
cv2.waitKey()
當參數選擇OTSU的時候,能夠根據計算,自動算出下限。但是我認為這一點並沒有什么特別的用途。
4、模糊處理
obj = cv2.imread( "e:/template/pig.jpg", 0)
blur= cv2.blur(obj,( 3, 3))
gaussBlur=cv2.GaussianBlur(obj,( 3, 3), 0)
median = cv2.medianBlur(obj, 5)
bilate = cv2.bilateralFilter(obj, 0.75, 0.75)
5、形態學變換
obj = cv2.imread( "e:/template/pig.jpg", 0)
opening = cv2.morphologyEx(obj,cv2.MORPH_OPEN,( 7, 7))
cv2.imshow( "obj",obj)
cv2.imshow( "opening",opening)
我喜歡這種寫法,這將有長遠影響。
6、梯度變化,包括1階、2階和混合的。
obj = cv2.imread( "e:/template/pig.jpg", 0)
laplacian = cv2.Laplacian(obj,cv2.CV_64F)
sobelx=cv2.Sobel(obj,cv2.CV_64F, 1, 0,ksize= 5)
sobely=cv2.Sobel(obj,cv2.CV_64F, 0, 1,ksize= 5)
7、梯度融合
曾經這段代碼很神秘的,但是今日使用Python來寫,就非常簡單。可以看出,Python用來處理二維矩陣信息是很強的。
# Standard imports
import cv2
import numpy  as np

 
A = cv2.imread( "e:/template/apple.jpg")
B = cv2.imread( "e:/template/orange.jpg")

G = A.copy()
gpA=[G]
for i  in range( 6):
    G = cv2.pyrDown(G)
    gpA.append(G)

G = B.copy()
gpB = [G]
for i  in range( 6):
    G = cv2.pyrDown(G)
    gpB.append(G)

lpA = [gpA[ 5]]
for i  in range( 5, 0,- 1):
    GE = cv2.pyrUp(gpA[i])
    L = cv2.subtract(gpA[i- 1],GE)
    lpA.append(L)

lpB = [gpB[ 5]]
for i  in range( 5, 0,- 1):
    GE = cv2.pyrUp(gpB[i])
    L = cv2.subtract(gpB[i- 1],GE)
    lpB.append(L)

LS = []
for la,lb  in zip(lpA,lpB):
    rows,cols,dpt= la.shape
    print(rows,cols)
    ls = np.hstack((la[:, 0:cols// 2],lb[:,cols// 2:]))  #直接橫向排列
    LS.append(ls)

ls_ = LS[ 0]
for i  in range( 1, 6):
    ls_ = cv2.pyrUp(ls_)
    ls_ = cv2.add(ls_,LS[i])

real = np.hstack((A[:,:cols// 2],B[:,cols// 2:]))
cv2.imshow( "ls_",ls_)
cv2.imshow( "real",real)
cv2.waitKey()
8、輪廓尋找
import cv2
import numpy  as np

src = cv2.imread( "e:/template/rectangle.jpg")
gray = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray, 127, 255, 0)
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
print(contours)
src = cv2.drawContours(src,contours,- 1,( 0, 255, 0), 3)
cv2.imshow( "src",src)
cv2.waitKey()
這里,使用 cv2.CHAIN_APPROX_NONE 或者不同的參數的話,會獲得不同的輪廓結果。這對於我現有的輪廓分析研究,也是有幫助的。
9、輪廓的最小​ 接圓和最大內切圓
外接圓比較簡單
(x,y),radius = cv2.minEnclosingCircle(contours[ 0])
center = (int(x),int(y))
radius = int(radius)
src = cv2.circle(src,center,radius,( 0, 255, 0), 2)
 
注意它這里的表示方法。內切圓則采用特殊方法。
# Get the contours
contours, _ = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# Calculate the distances to the contour
raw_dist = np.empty(thresh.shape, dtype=np.float32)
for i  in range(src.shape[ 0]):
     for j  in range(src.shape[ 1]):
        raw_dist[i,j] = cv.pointPolygonTest(contours[ 0], (j,i),  True)
minVal, maxVal, _, maxDistPt = cv.minMaxLoc(raw_dist)
minVal = abs(minVal)
maxVal = abs(maxVal)
# Depicting the  distances graphically
drawing = np.zeros((src.shape[ 0], src.shape[ 1],  3), dtype=np.uint8)
for i  in range(src.shape[ 0]):
     for j  in range(src.shape[ 1]):
         if raw_dist[i,j] <  0:
            drawing[i,j, 0] =  255 - abs(raw_dist[i,j]) *  255 / minVal
         elif raw_dist[i,j] >  0:
            drawing[i,j, 2] =  255 - raw_dist[i,j] *  255 / maxVal
         else:
            drawing[i,j, 0] =  255
            drawing[i,j, 1] =  255
            drawing[i,j, 2] =  255    
cv.circle(drawing,maxDistPt,int(maxVal),( 255, 255, 255))
cv.imshow( 'Source', src)
cv.imshow( 'Distance and inscribed circle', drawing)
cv.waitKey()
最大內接圓則復雜許多。
10、尋找輪廓的極點
contours, _  = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[ 0]
leftmost = tuple(cnt[cnt[:,:, 0].argmin()][ 0])
rightmost= tuple(cnt[cnt[:,:, 0].argmax()][ 0])
topmost  = tuple(cnt[cnt[:,:, 1].argmin()][ 0])
bottommost=tuple(cnt[cnt[:,:, 1].argmax()][ 0])
cv2.circle(src,leftmost, 5,( 0, 255, 0))
cv2.circle(src,rightmost, 5,( 0, 255, 255))
cv2.circle(src,topmost, 5,( 255, 255, 0))
cv2.circle(src,bottommost, 5,( 255, 0, 0))

cv2.imshow( "src",src)
這是一種很好的方法,能夠直接找出輪廓的各方向邊界。
11 模板匹配
src = cv.imread( "e:/template/lena.jpg", 0)
template = cv.imread( "e:/template/lenaface.jpg", 0)
w,h = template.shape
res = cv.matchTemplate(src,template,cv.TM_CCOEFF)
min_val,max_val,min_loc,max_loc = cv.minMaxLoc(res)
cv.rectangle(src,max_loc,(max_loc[ 0]+w,max_loc[ 1]+h),( 0, 0, 255), 2)
cv.imshow( "template",template)
cv.imshow( "src",src)
cv.waitKey()
我想體現的是python它的寫法有很大不同。
src = cv.imread( "e:/template/coin.jpg")
gray = cv.cvtColor(src,cv.COLOR_BGR2GRAY)
template = cv.imread( "e:/template/coincut.jpg", 0)
w,h = template.shape
res = cv.matchTemplate(gray,template,cv.TM_CCOEFF_NORMED)
threshold = 0.4
loc = np.where(res>=threshold)
print(loc)
for pt  in zip(*loc[:: 1]):
    cv.rectangle(src,pt,(pt[ 0]+w,pt[ 1]+h),( 0, 0, 255), 2)
 
cv.imshow( "template",template)
cv.imshow( "src",src)
cv.waitKey()
結合使用閾值,可以實現多目標匹配。
# Standard imports
import cv2  as cv
import numpy  as np

src = cv.imread( "e:/template/coin.jpg")
gray = cv.cvtColor(src,cv.COLOR_BGR2GRAY)
template = cv.imread( "e:/template/coincut.jpg", 0)
w,h = template.shape
res = cv.matchTemplate(gray,template,cv.TM_CCOEFF_NORMED)
threshold = 0.6
loc = np.where(res>=threshold)
print(loc)
for pt  in zip(*loc[::- 1]): #排序方法為height width
    print(pt)
    cv.rectangle(src,pt,(pt[ 0]+w,pt[ 1]+h),( 0, 0, 255), 2)
 
cv.imshow( "template",template)
cv.imshow( "src",src)
cv.waitKey()
特別需要注意其排序方法。但是這里的閾值選擇,也是超參數類型的。
12 HoughCircle
src = cv.imread( "e:/template/circle.jpg", 0)
src = cv.medianBlur(src, 5)
cimg = cv.cvtColor(src,cv.COLOR_GRAY2BGR)

circles = cv.HoughCircles(src,cv.HOUGH_GRADIENT, 1, 20,param1= 50,param2= 30,minRadius= 0,maxRadius= 0)
circles = np.uint16(np.around(circles))
for i  in circles[ 0,:]:
    cv.circle(cimg,(i[ 0],i[ 1]),i[ 2],( 0, 255, 0), 2)
    cv.circle(cimg,(i[ 0],i[ 1]), 2,( 0, 0, 255), 3)

cv.imshow( "src",cimg)
cv.waitKey()
13 風水嶺算法
# Standard imports
import cv2  as cv
import numpy  as np

src = cv.imread( "e:/template/water_coins.jpg")
gray =cv.cvtColor(src,cv.COLOR_BGR2GRAY)
_,thresh = cv.threshold(gray, 0, 255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)

kernel = np.ones(( 3, 3),np.uint8)
opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel,iterations= 2)
sur_bg = cv.dilate(opening,kernel)

dist_transform = cv.distanceTransform(opening, 1, 5)
_,sur_fg=cv.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
sur_fg = np.uint8(sur_fg)
unknow = cv.subtract(sur_bg,sur_fg)

_,markers1 = cv.connectedComponents(sur_fg)
markers = markers1+ 1
markers[unknow == 255] =  0

markers3 = cv.watershed(src,markers)
src[markers3 == - 1] = [ 255, 0, 0]
cv.imshow( "src",src)
 
cv.waitKey()
這個結果,具有參考價值。
 
 






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM