opencv-python基礎知識學習筆記
原博地址:https://www.cnblogs.com/silence-cho/p/10926248.html
1.圖像的讀入和存儲:
(1)函數格式:
#【1】讀取圖片,返回圖片對象
imread(img_path,flag)
img_path: 圖片的路徑,即使路徑錯誤也不會報錯,但打印返回的圖片對象爲None
flag:cv2.IMREAD_COLOR,讀取彩色圖片,圖片透明性會被忽略,爲默認參數,也可以傳入1
cv2.IMREAD_GRAYSCALE,按灰度模式讀取圖像,也可以傳入0
cv2.IMREAD_UNCHANGED,讀取圖像,包括其alpha通道,也可以傳入-1
#【2】
# (1)顯示圖片,窗口自適應圖片大小
imshow(window_name,img):
window_name: 指定窗口的名字
img:顯示的圖片對象
可以指定多個窗口名稱,顯示多個圖片
# (2)鍵盤綁定事件,阻塞監聽鍵盤按鍵,返回一個數字(不同按鍵對應的數字不同)
waitKey(millseconds)
millseconds: 傳入時間毫秒數,在該時間內等待鍵盤事件;傳入0時,會一直等待鍵盤事件
# (3)關閉窗口
destroyAllWindows(window_name)
window_name: 需要關閉的窗口名字,不傳入時關閉所有窗口
#【3】保存圖像
imwrite(img_path_name,img)
img_path_name:保存的文件名
img:文件對象
(2)應用舉例:
import cv2
img = cv2.imread("2.jpg")
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,img_threshold = cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY)
cv2.imshow("img",img)
cv2.imshow("thre",img_threshold)
key = cv2.waitKey(0)
if key==27: #按esc鍵時,關閉所有窗口
print(key)
cv2.destroyAllWindows()
cv2.imwrite("2-1.jpg", img_threshold)
2.圖像像素獲取和編輯:
img = cv2.imread("2.jpg")
# 【1】像素值獲取
(1)
pixel = img[100,100] #[57 63 68],獲取(100,100)處的像素值
img[100,100]=[57,63,99] #設置像素值
b = img[100,100,0] #57, 獲取(100,100)處,blue通道像素值
g = img[100,100,1] #63
r = img[100,100,2] #68
r = img[100,100,2]=99 #設置red通道值
(2)
piexl = img.item(100,100,2)
img.itemset((100,100,2),99)
# 【2】圖像性質獲取
img.shape #返回(280, 450, 3), 寬280(rows),長450(cols),3通道(channels)
img.size #返回378000,所有像素數量,=280*450*3
img.dtype #dtype('uint8')
# 【3】ROI截取:
roi = img[100:200,300:400] #截取100行到200行,列爲300到400列的整塊區域
img[50:150,200:300] = roi #將截取的roi移動到該區域 (50到100行,200到300列)
b = img[:,:,0] #截取整個藍色通道
b,g,r = cv2.split(img) #截取三個通道,比較耗時
img = cv2.merge((b,g,r))
3.添加邊界:
(1)函數格式:
cv2.copyMakeBorder()
參數:
img:圖像對象
top,bottom,left,right: 上下左右邊界寬度,單位爲像素值
borderType:
cv2.BORDER_CONSTANT, 帶顏色的邊界,需要傳入另外一個顏色值
cv2.BORDER_REFLECT, 邊緣元素的鏡像反射做爲邊界
cv2.BORDER_REFLECT_101/cv2.BORDER_DEFAULT
cv2.BORDER_REPLICATE, 邊緣元素的複製做爲邊界
CV2.BORDER_WRAP
value: borderType爲cv2.BORDER_CONSTANT時,傳入的邊界顏色值,如[0,255,0]
(2)應用舉例:
import cv2 as cv
import matplotlib.pyplot as plt
img2 = cv.imread("2.jpg")
img = cv.cvtColor(img2,cv.COLOR_BGR2RGB) #matplotlib的圖像爲RGB格式
constant = cv.copyMakeBorder(img,20,20,20,20,cv.BORDER_CONSTANT,value=[0,255,0]) #綠色
reflect = cv.copyMakeBorder(img,20,20,20,20,cv.BORDER_REFLECT)
reflect01 = cv.copyMakeBorder(img,20,20,20,20,cv.BORDER_REFLECT_101)
replicate = cv.copyMakeBorder(img,20,20,20,20,cv.BORDER_REPLICATE)
wrap = cv.copyMakeBorder(img,20,20,20,20,cv.BORDER_WRAP)
titles = ["constant","reflect","reflect01","replicate","wrap"]
images = [constant,reflect,reflect01,replicate,wrap]
for i in range(5):
plt.subplot(2,3,i+1),plt.imshow(images[i]),plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
4.像素算術運算:
(1)函數格式:
# 【1】注意:圖像相加時應該用cv2.add(img1,img2)代替img1+img2
cv2.add()
參數:
img1:圖片對象1
img2:圖片對象2
mask:None (掩膜,一般用灰度圖做掩膜,img1和img2相加後,和掩膜與運算,從而達到掩蓋部分區域的目的)
dtype:-1
# 【2】兩張圖片相加,分別給予不同權重,實現圖片融合和透明背景等效果
cv2.addWeighted()
參數:
img1:圖片對象1
alpha:img1的權重
img2:圖片對象2
beta:img1的權重
gamma:常量值,圖像相加後再加上常量值
dtype:返回圖像的數據類型,默認爲-1,和img1一樣
(img1*alpha+img2*beta+gamma)
(2)應用舉例:
# 【1】
import cv2 as cv
import numpy as np
img1 = cv.imread("2.jpg",0)
roi_img = np.zeros(img1.shape[0:2],dtype=np.uint8)
roi_img[100:280,400:550] = 255
img_add = cv.add(img1,img1)
img_add_mask = cv.add(img1,img1,mask=roi_img)
cv.imshow("img_add",img_add)
cv.imshow("img_add_mask",img_add_mask)
cv.waitKey(0)
cv.destroyAllWindows()
# 【2】
import cv2 as cv
img1 = cv.imread("1.jpg")
img = img1[0:426,43:683]
img2 = cv.imread("2.jpg")
blend = cv.addWeighted(img,0.5,img2,0.9,0) #兩張圖的大小和通道也應該相同
cv.imshow("blend",blend)
cv.waitKey()
cv.destroyAllWindows()
5.圖像位運算:
(1)函數格式:
# 【1】與運算
cv2.btwise_and():
參數:
img1:圖片對象1
img2:圖片對象2
mask:掩膜
# 【2】或運算
cv2.bitwise_or():
參數:
img1:圖片對象1
img2:圖片對象2
mask:掩膜
# 【3】非運算
cv2.bitwise_not():
img1:圖片對象1
mask:掩膜
# 【4】異或運算,相同爲1,不同爲0(1^1=0,1^0=1)
cv2.bitwise_xor():
img1:圖片對象1
img2:圖片對象2
mask:掩膜
(2)應用舉例:
import cv2 as cv
import matplotlib.pyplot as plt
img1 = cv.imread("1.png")
rows,cols = img1.shape[0:2]
img2 = cv.imread("2.jpg")
roi = img2[0:rows,0:cols]
img1_gray = cv.cvtColor(img1,cv.COLOR_BGR2GRAY)
ret,img1_thres = cv.threshold(img1_gray,200,255,cv.THRESH_BINARY_INV)
img1_fg =cv.add(img1,img1,mask=img1_thres) #logo圖案的前景
img1_thres_inv = cv.bitwise_not(img1_thres)
roi_bg = cv.add(roi,roi,mask=img1_thres_inv) #roi圖案的背景
img_add = cv.add(img1_fg,roi_bg) #背景和前景相加
img2[0:rows,0:cols] = img_add
cv.imshow("gray",img1_gray)
cv.imshow("thres",img1_thres)
cv.imshow("fg",img1_fg)
cv.imshow("tinv",img1_thres_inv)
cv.imshow("roi_bg",roi_bg)
cv.imshow("img_add",img_add)
cv.imshow("img2",img2)
cv.waitKey(0)
cv.destroyAllWindows()
6.圖像顏色空間轉換:
# 【1】
cv2.cvtColor()
參數:
img: 圖像對象
code:
cv2.COLOR_RGB2GRAY: RGB轉換到灰度模式
cv2.COLOR_RGB2HSV: RGB轉換到HSV模式(hue,saturation,Value)
# 【2】
cv2.inRange()
參數:
img: 圖像對象/array
lowerb: 低邊界array, 如lower_blue = np.array([110,50,50])
upperb:高邊界array, 如 upper_blue = np.array([130,255,255])
mask = cv2.inRange(hsv, lower_green, upper_green)
7.性能評價:
import cv2
img1 = cv2.imread("1.png")
e1 = cv2.getTickCount()
for i in xrange(5,49,2):
img1 = cv2.medianBlur(img1,i)
e2 = cv2.getTickCount()
t = (e2 - e1)/cv2.getTickFrequency()
print(t)
8.綁定TrackBar到圖像:
(1)函數格式:
# 【1】爲窗口添加trackbar
cv2.createTrackbar()
參數:
trackbarname: trackbar的名字
winname: 窗口的名字
value: trackbar創建時的值
count:trackbar能設置的最大值,最小值總爲0
onChange:trackbar值發生變化時的回調函數,trackbar的值作爲參數傳給onchange
# 【2】獲取某個窗口中trackbar的值
cv2.getTrackbarPos()
參數:
trackbarname: trackbar的名字
winname: 窗口的名字
(2)應用舉例:
import cv2 as cv
import numpy as np
def nothing(args):
pass
img = cv.imread("1.png")
img_hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
cv.namedWindow('tracks')
cv.createTrackbar("LH","tracks",0,255,nothing)
cv.createTrackbar("LS","tracks",0,255,nothing)
cv.createTrackbar("LV","tracks",0,255,nothing)
cv.createTrackbar("UH","tracks",255,255,nothing)
cv.createTrackbar("US","tracks",255,255,nothing)
cv.createTrackbar("UV","tracks",255,255,nothing)
while(1):
l_h = cv.getTrackbarPos("LH","tracks")
l_s = cv.getTrackbarPos("LS","tracks")
l_v = cv.getTrackbarPos("LV","tracks")
u_h = cv.getTrackbarPos("UH","tracks")
u_s = cv.getTrackbarPos("US","tracks")
u_v = cv.getTrackbarPos("UV","tracks")
lower_b = np.array([l_h,l_s,l_v])
upper_b = np.array([u_h,u_s,u_v])
mask = cv.inRange(img_hsv,lower_b,upper_b)
res = cv.add(img,img,mask=mask)
cv.imshow("img",img)
cv.imshow("mask",mask)
cv.imshow("res",res)
k = cv.waitKey(1)
if k==27:
break
cv.destroyAllWindows()
9.圖像閾值分割:
(1)函數格式:
# 【1】
cv2.threshold():
參數:
img:圖像對象,必須是灰度圖
thresh:閾值
maxval:最大值
type:
cv2.THRESH_BINARY: 小於閾值的像素置爲0,大於閾值的置爲maxval
cv2.THRESH_BINARY_INV: 小於閾值的像素置爲maxval,大於閾值的置爲0
cv2.THRESH_TRUNC: 小於閾值的像素不變,大於閾值的置爲thresh
cv2.THRESH_TOZERO 小於閾值的像素置0,大於閾值的不變
cv2.THRESH_TOZERO_INV 小於閾值的不變,大於閾值的像素置0
返回值:
ret:閾值
img:閾值化處理後的圖像
# 【2】
cv2.adaptiveThreshold() 自適應閾值處理,圖像不同部位採用不同的閾值進行處理
參數:
img: 圖像對象,8-bit單通道圖
maxValue:最大值
adaptiveMethod: 自適應方法
cv2.ADAPTIVE_THRESH_MEAN_C :閾值爲周圍像素的平均值
cv2.ADAPTIVE_THRESH_GAUSSIAN_C : 閾值爲周圍像素的高斯均值(按權重)
threshType:
cv2.THRESH_BINARY: 小於閾值的像素置爲0,大於閾值的置爲maxValuel
cv2.THRESH_BINARY_INV: 小於閾值的像素置爲maxValue,大於閾值的置爲0
blocksize: 計算閾值時,自適應的窗口大小,必須爲奇數 (如3:表示附近3個像素範圍內的像素點,進行計算閾值)
C: 常數值,通過自適應方法計算的值,減去該常數值
(2)應用舉例:
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread("1.png",0)
ret,thre1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
adaptive_thre1 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,7,2)
adaptive_thre2 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,7,2)
titles = ["img","thre1","adaptive_thre1","adaptive_thre2"]
imgs = [img,thre1,adaptive_thre1,adaptive_thre2 ]
for i in range(4):
plt.subplot(2,2,i+1), plt.imshow(imgs[i],"gray")
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
10.圖像縮放:
(1)函數格式:
# 放大和縮小圖像
cv2.resize()
參數:
src: 輸入圖像對象
dsize:輸出矩陣/圖像的大小,爲0時計算方式如下:dsize = Size(round(fx*src.cols),round(fy*src.rows))
fx: 水平軸的縮放因子,爲0時計算方式: (double)dsize.width/src.cols
fy: 垂直軸的縮放因子,爲0時計算方式: (double)dsize.heigh/src.rows
interpolation:插值算法
cv2.INTER_NEAREST : 最近鄰插值法
cv2.INTER_LINEAR 默認值,雙線性插值法
cv2.INTER_AREA 基於局部像素的重採樣(resampling using pixel area relation)。對於圖像抽取(image decimation)來說,這可能是一個更好的方法。但如果是放大圖像時,它和最近鄰法的效果類似。
cv2.INTER_CUBIC 基於4x4像素鄰域的3次插值法
cv2.INTER_LANCZOS4 基於8x8像素鄰域的Lanczos插值
其中cv2.INTER_AREA 適合於圖像縮小, cv2.INTER_CUBIC (slow) & cv2.INTER_LINEAR 適合於圖像放大
(2)應用舉例 :
import cv2
import numpy as np
img = cv2.imread('1.jpg')
res = cv2.resize(img,None,fx=2, fy=2, interpolation = cv2.INTER_CUBIC)
height, width = img.shape[:2]
res = cv2.resize(img,(2*width, 2*height), interpolation = cv2.INTER_CUBIC)
11.仿射變換:
(1)函數格式 :
# 【1】仿射變換(從二維座標到二維座標之間的線性變換,且保持二維圖形的“平直性”和“平行性”。仿射變換可以通過一系列的原子變換的複合來實現,包括平移,縮放,翻轉,旋轉和剪切)
cv2.warpAffine()
參數:
img: 圖像對象
M:2*3 transformation matrix (轉變矩陣)
dsize:輸出矩陣的大小,注意格式爲(cols,rows) 即width對應cols,height對應rows
flags:可選,插值算法標識符,有默認值INTER_LINEAR,
如果插值算法爲WARP_INVERSE_MAP, warpAffine函數使用如下矩陣進行圖像轉dst(x,y)=src(M11*x+M12*y+M13,M21*x+M22*y+M23)
borderMode:可選, 邊界像素模式,有默認值BORDER_CONSTANT
borderValue:可選,邊界取值,有默認值Scalar()即0
# 【2】返回2*3的轉變矩陣(浮點型)
cv2.getRotationMatrix2D()
參數:
center:旋轉的中心點座標
angle:旋轉角度,單位爲度數,證書表示逆時針旋轉
scale:同方向的放大倍數
# 【3】仿射變換矩陣的計算,返回2*3的轉變矩陣
cv2.getAffineTransform()
參數:
src:原圖像中的三組座標,如np.float32([[50,50],[200,50],[50,200]])
dst: 轉換後的對應三組座標,如np.float32([[10,100],[200,50],[100,250]])
(2)應用舉例 :
# 【1】
import cv2
import numpy as np
img = cv2.imread('1.jpg',0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))
cv2.imshow('img',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 【2】
import cv2
import numpy as np
import matplotlib.pylab as plt
img = cv2.imread('2.jpg', 0)
rows, cols= img.shape
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(img,M,(cols,rows))
plt.subplot(121),plt.imshow(img)
plt.subplot(122),plt.imshow(dst)
plt.show()
12.透視變化:
(1)函數格式 :
# 【1】
cv2.getPerspectiveTransform() 返回3*3的轉變矩陣
參數:
src:原圖像中的四組座標,如 np.float32([[56,65],[368,52],[28,387],[389,390]])
dst: 轉換後的對應四組座標,如np.float32([[0,0],[300,0],[0,300],[300,300]])
# 【2】
cv2.wrapPerspective()
參數:
src: 圖像對象
M:3*3 transformation matrix (轉變矩陣)
dsize:輸出矩陣的大小,注意格式爲(cols,rows) 即width對應cols,height對應rows
flags:可選,插值算法標識符,有默認值INTER_LINEAR,
如果插值算法爲WARP_INVERSE_MAP, warpAffine函數使用如下矩陣進行圖像轉dst(x,y)=src(M11*x+M12*y+M13,M21*x+M22*y+M23)
borderMode:可選, 邊界像素模式,有默認值BORDER_CONSTANT
borderValue:可選,邊界取值,有默認值Scalar()即0
(2)應用舉例:
img = cv2.imread('1.png')
rows,cols,ch = img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(300,300))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
13:直方圖繪製:
灰度直方圖繪製:
1)可以利用opencv的calcHist()統計像素值出現次數,通過matploblib的plot()繪製;
2)可以直接利用matploblib的hist()方法。
(1)函數格式 :
# 【1】
cv2.calcHist()
參數:
img:輸入圖像,爲列表,如[img]
channels: 計算的通道,爲列表,如[0]表示單通道,[0,1]統計兩個通道
mask: 掩模,和輸入圖像大小一樣的矩陣,爲1的地方會進行統計(與圖像邏輯與後再統計);無掩模時爲None
histSize: 每一個channel對應的bins個數,爲列表,如[256]表示256個像素值
ranges: bins的邊界,爲列表,如[0,256]表示像素值範圍在0-256之間
accumulate: Accumulation flag
(2)應用舉例 :
# 【1】cv.calcHist
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread("2.jpg",0)
hist = cv.calcHist([img],[0],None,[256],[0,256])
plt.subplot(1,3,1),plt.plot(hist,color="r"),plt.axis([0,256,0,np.max(hist)])
plt.xlabel("gray level")
plt.ylabel("number of pixels")
plt.subplot(1,3,2),plt.hist(img.ravel(),bins=256,range=[0,256]),plt.xlim([0,256])
plt.xlabel("gray level")
plt.ylabel("number of pixels")
plt.subplot(1,3,3)
plt.plot(hist,color="r"),plt.axis([0,256,0,np.max(hist)])
plt.hist(img.ravel(),bins=256,range=[0,256]),plt.xlim([0,256])
plt.xlabel("gray level")
plt.ylabel("number of pixels")
plt.show()
# 【2】np.histogram
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread("2.jpg",0)
histogram,bins = np.histogram(img,bins=256,range=[0,256])
print(histogram)
plt.plot(histogram,color="g")
plt.axis([0,256,0,np.max(histogram)])
plt.xlabel("gray level")
plt.ylabel("number of pixels")
plt.show()
# 【3】plt.hist
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread("2.jpg",0)
rows,cols = img.shape
hist = img.reshape(rows*cols)
histogram,bins,patch = plt.hist(hist,256,facecolor="green",histtype="bar") #histogram即爲統計出的灰度值分佈
plt.xlabel("gray level")
plt.ylabel("number of pixels")
plt.axis([0,255,0,np.max(histogram)])
plt.show()
14:對比度增強:
(1)線性變換 :
1)函數格式:
cv2.convertScaleAbs(src,alpha,beta)
src: 圖像對象矩陣
dst:輸出圖像矩陣
alpha:y=ax+b中的a值
beta:y=ax+b中的b值
(對於計算後大於255的像素值會截斷爲255)
2)應用舉例:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread("2.jpg")
print(img)
img_bright = cv.convertScaleAbs(img,alpha=1.5,beta=0)
print(img_bright)
cv.imshow("img",img)
cv.imshow("img_bright",img_bright)
cv.waitKey(0)
cv.destroyAllWindows()
(2)直方圖規範化 :
直方圖正規化的係數固定,一般將原圖片的像素值範圍映射到[0,255]範圍內。
1)函數格式:
cv2.normalize(src,dst,alpha,beta,normType,dtype,mask)
參數:
src: 圖像對象矩陣
dst:輸出圖像矩陣(和src的shape一樣)
alpha:正規化的值,如果是範圍值,爲範圍的下限 (alpha – norm value to normalize to or the lower range boundary in case of the range normalization.)
beta:如果是範圍值,爲範圍的上限;正規化中不用到 ( upper range boundary in case of the range normalization; it is not used for the norm normalization.)
norm_type:normalize的類型
cv2.NORM_L1:將像素矩陣的1-範數做爲最大值(矩陣中值的絕對值的和)
cv2.NORM_L2:將像素矩陣的2-範數做爲最大值(矩陣中值的平方和的開方)
cv2.NORM_MINMAX:將像素矩陣的∞-範數做爲最大值 (矩陣中值的絕對值的最大值)
dtype: 輸出圖像矩陣的數據類型,默認爲-1,即和src一樣
mask:掩模矩陣,只對感興趣的地方歸一化
2)應用實例:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread("2.jpg")
img_norm=cv.normalize(img,dst=None,alpha=350,beta=10,norm_type=cv.NORM_MINMAX)
cv.imshow("img",img)
cv.imshow("img_norm",img_norm)
cv.waitKey(0)
cv.destroyAllWindows()
(3)伽瑪變換:
將輸入圖像的像素值除以255,歸一化到[0,1]區間,然後計算其γ次方值,用公式表示如下,其中I(r,c)爲歸一化後的像素值,當γ=1時原像素值不影響,當0<γ<1時,增大像素值,提高圖片對比度;反之γ>1時能降低圖片對比度。
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread("2.jpg")
img_norm = img/255.0 #注意255.0得采用浮點數
img_gamma = np.power(img_norm,0.4)*255.0
img_gamma = img_gamma.astype(np.uint8)
cv.imshow("img",img)
cv.imshow("img_gamma",img_gamma)
cv.waitKey(0)
cv.destroyAllWindows()
(4)全局直方圖均衡化:
直方圖均衡化的目的是將原圖片每個像素值的像素點個數進行重新分配到[0,255]的256個像素值上,使得每個像素值對應的像素點個數近似相等,即重新分配後,0-255的每個像素值對應的像素點個數近似爲(rows*cols/256)。
1)函數格式:
cv2.equalizeHist(src,dst)
src: 圖像對象矩陣,必須爲單通道的uint8類型的矩陣數據
dst:輸出圖像矩陣(和src的shape一樣)
2)應用舉例:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
import math
img = cv.imread("2.jpg",0)
img_equalize = cv.equalizeHist(img)
cv.imshow("img",img)
cv.imshow("img_equalize",img_equalize)
cv.waitKey(0)
cv.destroyAllWindows()
(5)限制對比度自適應直方圖均衡化:
相比全局直方圖均衡化,自適應直方圖均衡化將圖像劃分爲不重疊的小塊,在每一小塊進行直方圖均衡化,但若小塊內有噪聲,影響很大,需要通過限制對比度來進行抑制,即限制對比度自適應直方圖均衡化。如果限制對比度的閾值設置會40,在局部直方圖分佈中某個像素值出現次數爲45,那麼多出的5次像素點會被去掉,平均成其他像素值。
1)函數格式:
# 【1】
clahe=cv2.createCLAHE(clipLimit,tileGridSize)
clipLimit:限制對比度的閾值,默認爲40,直方圖中像素值出現次數大於該閾值,多餘的次數會被重新分配
tileGridSize:圖像會被劃分的size, 如tileGridSize=(8,8),默認爲(8,8)
# 【2】
calhe.apply(img) #對img進行限制對比度自適應直方圖均衡化
2)應用舉例:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
import math
img = cv.imread("2.jpg",0)
clahe = cv.createCLAHE(3,(8,8))
dst = clahe.apply(img)
cv.imshow("img",img)
cv.imshow("dst",dst)
cv.waitKey(0)
cv.destroyAllWindows()
15.二維離散卷積:
三種卷積類型:
1)Full卷積:從filter和圖像剛相交開始做卷積;
2)Same卷積:當filter的錨點(K)與圖像的邊角重合時,開始做卷積運算,filter的運動範圍比full模式小了一圈,Same卷積爲Full卷積的子集,即Full卷積的處理結果包括Same mode;
3)Valid卷積:當filter全部在圖像裏面的時候,進行卷積運算,可見filter的移動範圍較Same卷積更小了,同樣Valid 卷積爲Same卷積的子集。valid mode的卷積計算,填充邊界中的像素值不會參與計算,即無效的填充邊界不影響卷積,所以稱爲Valid mode。
from scipy import signal
# 【1】
signal.convolve2d(src,kernel,mode,boundary,fillvalue)
參數:
src: 輸入的圖像矩陣,只支持單通的(即二維矩陣)
kernel:卷積核
mode:卷積類型:full, same, valid
boundary:邊界填充方式:fill,wrap, symm
fillvalue: 當boundary爲fill時,邊界填充的值,默認爲0
# 【2】 翻轉卷積核
dst = cv2.flip(src,flipCode)
src: 輸入矩陣
flipCode:0表示沿着x軸翻轉,1表示沿着y軸翻轉,-1表示分別沿着x軸,y軸翻轉
dst:輸出矩陣(和src的shape一樣)
# 【3】filter2D()進行same卷積
cv2.filter2D(src,dst,ddepth,kernel,anchor=(-1,-1),delta=0,borderType=cv2.BORDER_DEFAULT)
src: 輸入圖像對象矩陣
dst:輸出圖像矩陣
ddepth:輸出矩陣的數值類型
kernel:卷積核
anchor:卷積核錨點,默認(-1,-1)表示卷積核的中心位置
delat:卷積完後相加的常數
borderType:填充邊界類型
16.圖像平滑:
(1)高斯平滑:
1)函數格式:
# 【1】進行高斯平滑
dst = cv2.GaussianBlur(src,ksize,sigmaX,sigmay,borderType)
src: 輸入圖像矩陣,可爲單通道或多通道,多通道時分別對每個通道進行卷積
dst:輸出圖像矩陣,大小和數據類型都與src相同
ksize:高斯卷積核的大小,寬,高都爲奇數,且可以不相同
sigmaX: 一維水平方向高斯卷積核的標準差
sigmaY: 一維垂直方向高斯卷積核的標準差,默認值爲0,表示與sigmaX相同
borderType:填充邊界類型
# 【2】生成一維高斯卷積核
cv2.getGaussianKernel(ksize,sigma,ktype)
ksize:奇數,一維核長度
sigma:標準差
ktype:數據格式,應該爲CV_32F 或者 CV_64F
2)應用舉例:
# 【1】
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread("2.jpg")
img_gauss = cv.GaussianBlur(img,(3,3),1)
cv.imshow("img",img)
cv.imshow("img_gauss",img_gauss)
cv.waitKey(0)
cv.destroyAllWindows()
# 【2】
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal
def gaussianBlur(img,h,w,sigma,boundary="fill",fillvalue=0):
kernel_x = cv.getGaussianKernel(w,sigma,cv.CV_64F) #默認得到的爲垂直矩陣
kernel_x = np.transpose(kernel_x) #轉置操作,得到水平矩陣
#convolve2d只是對單通道進行卷積,若要實現cv.GaussianBlur()多通道高斯卷積,需要拆分三個通道進行,再合併
#水平方向卷積
gaussian_x = signal.convolve2d(img,kernel_x,mode="same",boundary=boundary,fillvalue=fillvalue)
#垂直方向卷積
kernel_y = cv.getGaussianKernel(h,sigma,cv.CV_64F)
gaussian_xy = signal.convolve2d(gaussian_x,kernel_y,mode="same",boundary=boundary,fillvalue=fillvalue)
#cv.CV_64F數據轉換爲uint8
gaussian_xy = np.round(gaussian_xy)
gaussian_xy = gaussian_xy.astype(np.uint8)
return gaussian_xy
if __name__=="__main__":
img = cv.imread("2.jpg",0)
img_gauss = gaussianBlur(img,3,3,1)
cv.imshow("img",img)
cv.imshow("img_gauss",img_gauss)
cv.waitKey(0)
cv.destroyAllWindows()
(2)均值濾波:
1)函數格式:
# 【1】
cv2.boxFilter(src,ddepth,ksize,dst,anchor,normalize,borderType)
src: 輸入圖像對象矩陣,
ddepth:數據格式,位深度
ksize:高斯卷積核的大小,格式爲(寬,高)
dst:輸出圖像矩陣,大小和數據類型都與src相同
anchor:卷積核錨點,默認(-1,-1)表示卷積核的中心位置
normalize:是否歸一化 (若卷積核3*5,歸一化卷積核需要除以15)
borderType:填充邊界類型
# 【2】
cv2.blur(src,ksize,dst,anchor,borderType)
src: 輸入圖像對象矩陣,可以爲單通道或多通道
ksize:高斯卷積核的大小,格式爲(寬,高)
dst:輸出圖像矩陣,大小和數據類型都與src相同
anchor:卷積核錨點,默認(-1,-1)表示卷積核的中心位置
borderType:填充邊界類型
2)應用舉例:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread("2.jpg")
img_blur = cv.blur(img,(3,5))
# img_blur = cv.boxFilter(img,-1,(3,5))
cv.imshow("img",img)
cv.imshow("img_blur",img_blur)
cv.waitKey(0)
cv.destroyAllWindows()
(3)中值濾波:
1)函數格式:
cv2.medianBlur(src,ksize,dst)
src: 輸入圖像對象矩陣,可以爲單通道或多通道
ksize:核的大小,格式爲 3 #注意不是(3,3)
dst:輸出圖像矩陣,大小和數據類型都與src相同
2)應用舉例:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
import random
img = cv.imread("2.jpg")
rows,cols = img.shape[:2]
#加入椒鹽噪聲
for i in range(100):
r = random.randint(0,rows-1)
c = random.randint(0,cols-1)
img[r,c]=255
img_medianblur = cv.medianBlur(img,5)
cv.imshow("img",img)
cv.imshow("img_medianblur",img_medianblur)
cv.waitKey(0)
cv.destroyAllWindows()
(4)雙邊濾波:
雙邊濾波在平滑的同時還能保持圖像中物體的輪廓信息。雙邊濾波在高斯平滑的基礎上引入了灰度值相似性權重因子,所以在構建其卷積核核時,要同時考慮空間距離權重和灰度值相似性權重。在進行卷積時,每個位置的鄰域內,根據和錨點的距離d構建距離權重模板,根據和錨點灰度值差異r構建灰度值權重模板,結合兩個模板生成該位置的卷積核。
1)函數格式:
dst = cv2.bilateralFilter(src,d,sigmaColor,sigmaSpace,borderType)
src: 輸入圖像對象矩陣,可以爲單通道或多通道
d:用來計算卷積核的領域直徑,如果d<=0,從sigmaSpace計算d
sigmaColor:顏色空間濾波器標準偏差值,決定多少差值之內的像素會被計算(構建灰度值模板)
sigmaSpace:座標空間中濾波器標準偏差值。如果d>0,設置不起作用,否則根據它來計算d值(構建距離權重模板)
2)應用舉例:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
import random
import math
img = cv.imread("2.jpg")
img_bilateral = cv.bilateralFilter(img,0,0.2,40)
cv.imshow("img",img)
cv.imshow("img_bilateral",img_bilateral)
cv.waitKey(0)
cv.destroyAllWindows()
(5)聯合雙邊濾波:
雙邊濾波是根據原圖中不同位置灰度相似性來構建相似性權重模板,而聯合濾波是先對原圖進行高斯平滑,然後根據平滑後的圖像灰度值差異建立相似性模板,再與距離權重模板相乘得到最終的卷積核,最後再對原圖進行處理。所以相比於雙邊濾波,聯合雙邊濾波只是建立灰度值相似性模板的方法不一樣。
opencv 2中不支持聯合雙邊濾波,opencv 3中除了主模塊還引入了contrib,其中的ximgproc模塊包括了聯合雙邊濾波的算法。因此如果需要使用opencv的聯合雙邊濾波,需要安裝opencv-contrib-python包。
1)函數格式:
dst = cv2.xmingproc.jointBilateralFilter(joint,src,d,sigmaColor,sigmaSpace,borderType)
joint: 進行聯合濾波的導向圖像,可以爲單通道或多通道,保持邊緣的濾波算法時常採用src
src: 輸入圖像對象矩陣,可以爲單通道或多通道
d:用來計算卷積核的領域直徑,如果d<0,從sigmaSpace計算d
sigmaColor:顏色空間濾波器標準偏差值,決定多少差值之內的像素會被計算(構建灰度值模板)
sigmaSpace:座標空間中濾波器標準偏差值。如果d>0,設置不起作用,否則根據它來計算d值(構建距離權重模板)
2)應用舉例:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
import random
import math
src = cv.imread("2.jpg")
joint = cv.GaussianBlur(src,(7,7),1,0)
dst = cv.ximgproc.jointBilateralFilter(joint,src,33,2,0)
# dst = cv.ximgproc.jointBilateralFilter(src,src,33,2,0) #採用src作爲joint
cv.imshow("img",src)
cv.imshow("joint",joint)
cv.imshow("dst",dst)
cv.waitKey(0)
cv.destroyAllWindows()
(6)導向濾波:
導向濾波也是需要一張圖片作爲引導圖片,來表明邊緣,物體等信息,作爲保持邊緣濾波算法,可以採用自身作爲導向圖片。opencv2中暫不支持導向濾波, 同樣在opencv-contrib-python包的ximgproc模塊提供了導向濾波函數。
1)函數格式:
cv2.ximgproc.guidedFilter(guide,src,radius,eps,dDepth)
guide: 導向圖片,單通道或三通道
src: 輸入圖像對象矩陣,可以爲單通道或多通道
radius:用來計算卷積核的領域直徑
eps:規範化參數, eps的平方類似於雙邊濾波中的sigmaColor(顏色空間濾波器標準偏差值)
(regularization term of Guided Filter. eps2 is similar to the sigma in the color space into bilateralFilter.)
dDepth: 輸出圖片的數據深度
2)應用實例:
import cv2 as cv
src = cv.imread("2.jpg")
dst = cv.ximgproc.guidedFilter(src,src,33,2,-1)
cv.imshow("img",src)
cv.imshow("dst",dst)
cv.waitKey(0)
cv.destroyAllWindows()
17.腐蝕處理:
(1)函數格式:
# 【1】獲得腐蝕核
kernel=cv2.getStructuringElement(shape,ksize,anchor)
shape:核的形狀
cv2.MORPH_RECT: 矩形
cv2.MORPH_CROSS: 十字形(以矩形的錨點爲中心的十字架)
cv2.MORPH_ELLIPSE:橢圓(矩形的內切橢圓)
ksize: 核的大小,矩形的寬,高格式爲(width,height)
anchor: 核的錨點,默認值爲(-1,-1),即核的中心點
# 【2】執行腐蝕操作
dst=cv2.erode(src,kernel,anchor,iterations,borderType,borderValue):
src: 輸入圖像對象矩陣,爲二值化圖像
kernel:進行腐蝕操作的核,可以通過函數getStructuringElement()獲得
anchor:錨點,默認爲(-1,-1)
iterations:腐蝕操作的次數,默認爲1
borderType: 邊界種類,有默認值
borderValue:邊界值,有默認值
(2)應用實例:
import cv2 as cv
img = cv.imread("2.png")
img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,img_thr = cv.threshold(img_cvt,200,255,cv.THRESH_BINARY_INV)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,5))
dst = cv.erode(img_thr,kernel,iterations=1)
cv.imshow("img",img)
cv.imshow("img_thr",img_thr)
cv.imshow("dst",dst)
cv.waitKey(0)
cv.destroyAllWindows()
18.膨脹處理:
(1)函數格式:
dst = cv2.dilate(src,kernel,anchor,iterations,borderType,borderValue)
src: 輸入圖像對象矩陣,爲二值化圖像
kernel:進行腐蝕操作的核,可以通過函數getStructuringElement()獲得
anchor:錨點,默認爲(-1,-1)
iterations:腐蝕操作的次數,默認爲1
borderType: 邊界種類
borderValue:邊界值
(2)應用實例:
import cv2 as cv
img = cv.imread("2.jpg")
img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,img_thr = cv.threshold(img_cvt,500,255,cv.THRESH_BINARY_INV)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,5))
dst = cv.dilate(img_thr,kernel,iterations=1)
cv.imshow("img",img)
cv.imshow("img_thr",img_thr)
cv.imshow("dst",dst)
cv.waitKey(0)
cv.destroyAllWindows()
19.開運算/閉運算/形態學梯度/頂帽/底帽:
開運算:先進行腐蝕操作,後進行膨脹操作,主要用來去除一些較亮的部分,即先腐蝕掉不要的部分,再進行膨脹;
閉運算:先進行膨脹操作,後進行腐蝕操作,主要用來去除一些較暗的部分;
形態學梯度:膨脹運算結果減去腐蝕運算結果,可以拿到輪廓信息;
頂帽運算:原圖像減去開運算結果;
底帽運算:原圖像減去閉運算結果。
(1)函數格式:
dst = cv2.morphologyEx(src,op,kernel,anchor,iterations,borderType,borderValue)
src: 輸入圖像對象矩陣,爲二值化圖像
op: 形態學操作類型
cv2.MORPH_OPEN 開運算
cv2.MORPH_CLOSE 閉運算
cv2.MORPH_GRADIENT 形態梯度
cv2.MORPH_TOPHAT 頂帽運算
cv2.MORPH_BLACKHAT 底帽運算
kernel:進行腐蝕操作的核,可以通過函數getStructuringElement()獲得
anchor:錨點,默認爲(-1,-1)
iterations:腐蝕操作的次數,默認爲1
borderType: 邊界種類
borderValue:邊界值
(2)應用實例:
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread("2.jpg")
img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,img_thr = cv.threshold(img_cvt,20,255,cv.THRESH_BINARY_INV)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,5))
open = cv.morphologyEx(img_thr,cv.MORPH_OPEN,kernel,iterations=1)
close = cv.morphologyEx(img_thr,cv.MORPH_CLOSE,kernel,iterations=1)
gradient = cv.morphologyEx(img_thr,cv.MORPH_GRADIENT,kernel,iterations=1)
tophat = cv.morphologyEx(img_thr,cv.MORPH_TOPHAT,kernel,iterations=1)
blackhat = cv.morphologyEx(img_thr,cv.MORPH_BLACKHAT,kernel,iterations=1)
images=[img_thr,open,close,gradient,tophat,blackhat]
titles=["img_thr","open","close","gradient","tophat","blackhat"]
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],"gray")
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
20.直線、圓、矩形、文字的繪製:
# 【1】繪製直線
# img、ps、pe、color爲必須參數,其它爲可選項
cv2.line(img, ps, pe, color, thickness, lineType, shift)
參數:
img:要畫的直線所在的矩形或圖像
ps:直線的起點位置,注意這是一個座標點,類似(X,Y)
pe:直線的終點位置,同上
color:直線的顏色,顏色值爲BGR,即:(0,0,255)爲紅色
thickness:線條寬度
lineType:線條類型,三個參數可選LINE_4、LINE_8、LINE_AA,感興趣的可以自己試一下
shift:不常用,直線座標點小數點位數
# 【2】繪製圓
# img、center、radius、color爲必須參數,其它爲可選項
cv2.circle(img, center, radius, color, thickness, lineType, shift)
參數:
img:要畫的圓所在的矩形或圖像
center:圓心座標
radius:圓的半徑值
color:圓邊框顏色,顏色值爲BGR,即:(0,0,255)爲紅色
thickness:圓邊框大小,負值表示該圓是一個填充圖形
lineType:線條類型,三個參數可選0,4,8,感興趣的親測
shift:圓心座標和半徑的小數點位數
# 【3】繪製橢圓
# img/center/axes/rotateAngle/startAngle/endAngle/color爲必須參數,其它爲可選項
cv2.ellipse(img, center, axes, rotateAngle, startAngle, endAngle, color, thickness, lineType, shift)
參數:
img:要畫的橢圓所在的矩形或圖像
center:橢圓的圓心座標,注意這是一個座標值
axes:橢圓的長軸和短軸的長度,這是一個元組信息
rotateAngle:橢圓旋轉的角度
startAngle:橢圓弧起始角度
endAngle:橢圓弧終止角度
color:橢圓線條顏色,顏色值爲BGR,即:(0,0,255)爲紅色
thickness:橢圓的線條寬度
lineType:線條類型,三個參數可選LINE_4、LINE_8、LINE_AA,感興趣的可以親測
shift:橢圓座標點小數點位數
# 【4】繪製矩形
# img/ps/pe/color爲必須參數,其它爲可選項
cv2.rectangle(img, ps, pe, color, thickness, lineType, shift)
參數:
img:矩形所在的矩形或圖像
ps:矩形左上角點的座標
pe:矩形右下角點的座標
color:線條顏色,顏色值爲BGR,即:(0,0,255)爲紅色
thickness:矩形線條寬度
lineType:線條類型,三個參數可選LINE_4、LINE_8、LINE_AA,感興趣的可以親測
shift:座標點小數點位數
# 【5】繪製多邊形
# img/pts/isClosed/color爲必須參數,其它爲可選項
cv2.polylines(img, pts, isClosed, color, thickness, lineType, shift)
參數:
img:多邊形所在的矩形或圖像
pts:多邊形各邊的座標點組成的一個列表,是一個numpy的數組類型
isClosed:值爲True或False,若爲True則表示一個閉合的多邊形,若爲False則不閉合
color:線條顏色,顏色值爲BGR,即:(0,0,255)爲紅色
thickness:線條寬度
lineType:線條類型,三個參數可選LINE_4、LINE_8、LINE_AA,感興趣的可以親測
shift:座標點小數點位數
# 【6】繪製字符
# img/text/org/fontFace/fontScale/color爲必須參數,其它爲可選項
cv2.putText(img, text, org, fontFace, fontScale, color, thickness, lineType, bottomLeftOrigin)
參數:
img:文字要放置的矩形或圖像
text:文字內容
org:文字在圖像中的左下角座標
fontFace:字體類型,可選參數有以下幾種
FONT_HERSHEY_SIMPLEX,
FONT_HERSHEY_PLAIN,
FONT_HERSHEY_DUPLEX,
FONT_HERSHEY_COMPLEX,
FONT_HERSHEY_TRIPLEX,
FONT_HERSHEY_COMPLEX_SMALL,
FONT_HERSHEY_SCRIPT_SIMPLEX,
orFONT_HERSHEY_SCRIPT_COMPLEX
上述類型的字體可以結合FONT_HERSHEY_ITALIC一起來使用,從而使字體產生斜體效果。
fontScale:縮放比例,用該值乘以程序字體默認大小即爲字體大小
color:字體顏色,顏色值爲BGR,即:(0,0,255)爲紅色
thickness:字體線條寬度
bottomLeftOrigin:默認爲 true,即表示圖像數據原點在左下角;若爲False則表示圖像數據原點在左上角。
21.邊緣檢測:
(1)Canny邊緣檢測:
平滑圖像:使用高斯濾波器與圖像進行卷積,平滑圖像,以減少邊緣檢測器上明顯的噪聲影響;
計算圖像的梯度和方向:圖像中的邊緣可以指向各個方向,這裏計算圖像的梯度,並將梯度分類爲垂直、水平和斜對角;
非最大值抑制:利用上一步計算出來的梯度方向,檢測某一像素在梯度的正方向和負方向上是否是局部最大值,如果是,則該像素點保留爲邊緣點,否則該像素點將被抑制;
雙閾值算法檢測和連接邊緣:仍然存在由於噪聲和顏色變化引起的一些邊緣像素。爲了解決這些雜散響應,必須用弱梯度值過濾邊緣像素,並保留具有高梯度值的邊緣像素,可以通過選擇高低閾值來實現。
1)函數格式:
canny = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])
參數:
image: 處理的原圖像,該圖像必須爲單通道的灰度圖
threshold1: 最小閾值
threshold2 最大閾值
2)應用實例:
import os
import cv2
img = cv2.imread('2.jpg', 0) #轉化爲灰度圖
img_color = img
blur = cv2.GaussianBlur(img, (3, 3), 0) # 用高斯濾波處理原圖像降噪
canny = cv2.Canny(blur, 50, 150) # 50是最小閾值,150是最大閾值
cv2.namedWindow("canny",0);#可調大小
cv2.namedWindow("1",0);#可調大小
cv2.imshow('1', img)
cv2.imshow('canny', canny)
cv2.waitKey(0)
cv2.destroyAllWindows()
(2)Sobel邊緣檢測:
Sobel算子包含兩個3*3矩陣,分別爲橫向和縱向,將之與圖像做平面卷積,可分別得出橫向及縱向的高度差分近似值,圖像的每一個像素點的橫向與縱向灰度值平方和開方獲得該點灰度的大小。
1)函數格式:
# 【1】
Sobel_x_or_y = cv2.Sobel(src, ddepth, dx, dy, dst, ksize, scale, delta, borderType)
參數:
src:需要處理的圖像;
ddepth:圖像的深度,-1表示採用的是與原圖像相同的深度,目標圖像的深度必須大於等於原圖像的深度;
dx和dy:求導的階數,0表示這個方向上沒有求導,一般爲0、1、2。
# 【2】
convertScaleAbs()
# Sobel函數求完導數後會有負值,還有會大於255的值,convertScaleAbs()函數將sobel算子的處理結果轉換爲uint8形式,否則將無法顯示圖像
2)應用實例:
import os
import cv2
img = cv2.imread('2.jpg', 0) #轉化爲灰度圖
x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1)
# cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])
# alpha是伸縮係數,beta是加到結果上的一個值,結果返回uint類型的圖像
Scale_absX = cv2.convertScaleAbs(x)
Scale_absY = cv2.convertScaleAbs(y)
result = cv2.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
cv2.namedWindow("result",0);#可調大小
cv2.namedWindow("1",0);#可調大小
cv2.imshow('1', img)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
(3)findContours()函數:
1)函數格式:
# 【1】
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])
參數:
image:尋找輪廓的圖像;
mode:輪廓的檢索模式,有四種:
1)cv2.RETR_EXTERNAL表示只檢測外輪廓
2)cv2.RETR_LIST檢測的輪廓不建立等級關係
3)cv2.RETR_CCOMP建立兩個等級的輪廓,上面的一層爲外邊界,裏面的一層爲內孔的邊界信息。如果內孔內還有一個連通物體,這個物體的邊界也在頂層。
4)cv2.RETR_TREE建立一個等級樹結構的輪廓。
method:爲輪廓的近似辦法
1)cv2.CHAIN_APPROX_NONE存儲所有的輪廓點,相鄰的兩個點的像素位置差不超過1,即max(abs(x1-x2),abs(y2-y1))==1
2)cv2.CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點座標,例如一個矩形輪廓只需4個點來保存輪廓信息
3) cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似
返回值:
opencv2返回兩個值:contours:hierarchy。
opencv3會返回三個值,分別是img, countours, hierarchy。
# 【2】在圖像上繪製輪廓。
cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])
參數:
image:指明在哪幅圖像上繪製輪廓;
contours:輪廓本身,在Python中是一個list。
contourIdx:指定繪製輪廓list中的哪條輪廓,如果是-1,則繪製其中的所有輪廓。
thickness:表明輪廓線的寬度,如果是-1(cv2.FILLED),則爲填充模式。
22.模版匹配:
模板匹配的原理就是不斷地在原圖中移動模板圖像去比較,模板匹配也是應用卷積來實現的:假設原圖大小爲W×H,模板圖大小爲w×h,那麼生成圖大小是(W-w+1)×(H-h+1),生成圖中的每個像素值表示原圖與模板的匹配程度。
(1)函數格式:
# 【1】執行目標匹配
cv2.matchTemplate(image, templ, method, result=None, mask=None)
參數:
image:待搜索圖像
templ:模板圖像
result:匹配結果
method:計算匹配程度的方法:
1)平方差匹配CV_TM_SQDIFF:用兩者的平方差來匹配,最好的匹配值爲0
2)歸一化平方差匹配CV_TM_SQDIFF_NORMED
3)相關匹配CV_TM_CCORR:用兩者的乘積匹配,數值越大表明匹配程度越好
4)歸一化相關匹配CV_TM_CCORR_NORMED
5)相關係數匹配CV_TM_CCOEFF:用兩者的相關係數匹配,1表示完美的匹配,-1表示最差的匹配
6)歸一化相關係數匹配CV_TM_CCOEFF_NORMED
# 【2】獲取最後的最佳匹配結果獲取最後的最佳匹配結果
# 獲取一個矩陣a的最小值,最大值,並得到最大值,最小值的索引。
cv2.minMaxLoc(src, mask=None)
(2)應用實例:
# 【1】
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('2.jpg', 0)
template = cv2.imread('pattern.jpg', 0)
h, w = template.shape[:2] # rows->h, cols->w
# 相關係數匹配方法:cv2.TM_CCOEFF
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
left_top = max_loc # 左上角
right_bottom = (left_top[0] + w, left_top[1] + h) # 右下角
cv2.rectangle(img, left_top, right_bottom, 255, 2) # 畫出矩形位置
# 【2】多目標模版匹配
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 1.讀入原圖和模板
img_rgb = cv2.imread('marioimg.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('mariopattern.jpg', 0)
h, w = template.shape[:2]
# 2.標準相關模板匹配
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
# 3.np.where返回res中值大於0.8的所有座標
loc = np.where(res >= threshold) # 匹配程度大於%80的座標y,x
for pt in zip(*loc[::-1]): # 因爲loc是先y座標再x座標,所以用loc[::-1]翻轉一下,然後再用zip函數拼接在一起
right_bottom = (pt[0] + w, pt[1] + h)
cv2.rectangle(img_rgb, pt, right_bottom, (0, 0, 255), 2)
cv2.imshow('1', img_rgb)
cv2.waitKey(0)
23.凸包:
(1)函數格式:
# 【1】多邊形逼近
approx = cv2.approxPolyDP(cnt, epsilon, Flag)
參數:
cnt:待處理輪廓
epsilon: 距離值,表示多邊形的輪廓接近實際輪廓的程度,值越小,越精確;
Flag:表示是否閉合
# 【2】尋找凸包,獲取凸包的角點
hull2 = cv2.convexHull(cnt, returnPoints=False)
參數:
cnt:待處理輪廓
returnPoints:可選參數,默認是True,代表返回角點的x/y座標;如果爲False的話,表示返回輪廓中是凸包角點的索引
# 【3】判斷輪廓是否是凸形的
cv2.isContourConvex(hull)
# 【4】計算點到輪廓的最短距離(也就是垂線)
dist = cv2.pointPolygonTest(cnt, (100, 100), True)
(2)應用實例:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 1.先找到輪廓
img = cv2.imread('marioimg.jpg', 0)
_, thresh = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
contours, hierarchy = cv2.findContours(thresh, 3, 2)
image1 = cv2.drawContours(img, contours, -1, 255)
cv2.imshow('1', image1)
cnt = contours[0]
# 2.尋找凸包,得到凸包的角點
hull = cv2.convexHull(cnt)
# 3.繪製凸包
image = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
cv2.polylines(image, [hull], True, (0, 255, 0), 2)
cv2.imshow('3', image)
cv2.waitKey(0)
24.計算輪廓特徵:
(1)函數格式:
# 【1】輪廓面積
area = cv2.contourArea(cnt)
# 【2】輪廓周長
perimeter = cv2.arcLength(cnt, True)
參數:
參數2表示輪廓是否封閉,True表示封閉
# 【3】圖像矩(其中包含很多輪廓的特徵信息)
M = cv2.moments(cnt)
# 【4】rectangle1
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(img_color1, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 【5】rectangle2
rect = cv2.minAreaRect(cnt)
box = np.int0(cv2.boxPoints(rect)) # 矩形的四個角點取整
cv2.drawContours(img_color1, [box], 0, (255, 0, 0), 2) # 繪製矩形
# 【6】最小外接圓
(x, y), radius = cv2.minEnclosingCircle(cnt)
(x, y, radius) = np.int0((x, y, radius)) # 圓心和半徑取整
cv2.circle(img_color2, (x, y), radius, (0, 0, 255), 2) # 繪製圓
# 【7】橢圓擬合
ellipse = cv2.fitEllipse(cnt)
cv2.ellipse(img_color2, ellipse, (255, 255, 0), 2)
# 【8】利用hu矩陣返回兩個輪廓的形狀相似度,返回值越小,越相似
cv2.matchShapes(cnt_b, cnt_b, 1, 0.0)
參數:
參數3:匹配方法
參數4:是OpenCV的預留參數
25.霍夫變換:
(1)霍夫直線變換:
1)函數格式:
# 【1】霍夫直線變換
lines = cv2.HoughLines(edges, 0.8, np.pi / 180, 90)
參數:
參數1:要檢測的二值圖(一般是閾值分割或邊緣檢測後的圖)
參數2:距離r的精度,值越大,考慮越多的線
參數3:角度θ的精度,值越小,考慮越多的線
參數4:累加數閾值,值越小,考慮越多的線
# 【2】統計概率霍夫直線變換
lines = cv2.HoughLinesP(edges, 0.8, np.pi/180, 90, minLineLength=50, maxLineGap=10)
參數:
參數1:要檢測的二值圖(一般是閾值分割或邊緣檢測後的圖)
參數2:距離r的精度,值越大,考慮越多的線
參數3:角度θ的精度,值越小,考慮越多的線
參數4:累加數閾值,值越小,考慮越多的線
minLineLength:最短長度閾值,比這個長度短的線會被排除
maxLineGap:同一直線兩點之間的最大距離
2)應用實例:
# 【1】
import cv2
import numpy as np
img = cv2.imread('1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)
# 霍夫直線變換
lines = cv2.HoughLines(edges, 0.8, np.pi / 180, 90)
# 繪製直線
for line in lines:
rho, theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000 * (-b))
y1 = int(y0 + 1000 * (a))
x2 = int(x0 - 1000 * (-b))
y2 = int(y0 - 1000 * (a))
cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255))
cv2.imshow('1', img)
cv2.waitKey(0)
# 【2】
import cv2
import numpy as np
img = cv2.imread('1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)
lines = cv2.HoughLinesP(edges, 0.8, np.pi / 180, 90, minLineLength=50, maxLineGap=10)
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 1, lineType=cv2.LINE_AA)
cv2.imshow('1', img)
cv2.waitKey(0)
(2)霍夫圓變換:
1)函數格式:
circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 20, param2=30)
參數:
參數1:輪廓
參數2:變換方法,一般使用霍夫梯度法,詳情:HoughModes
參數3 dp=1:表示霍夫梯度法中累加器圖像的分辨率與原圖一致
參數4:兩個不同圓圓心的最短距離
參數5:param2跟霍夫直線變換中的累加數閾值一樣
2)應用實例:
import cv2
import numpy as np
img = cv2.imread('marioimg.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)
circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 50, param2=30)
circles = np.int0(np.around(circles))
for i in circles[0, :]:
cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 2) # 畫出外圓
cv2.circle(img, (i[0], i[1]), 2, (0, 0, 255), 3) # 畫出圓心
cv2.imshow('1', img)
cv2.waitKey(0)
26.圖像梯度提取:
(1)函數格式:
# 【1】Sobel算子
sobelx = cv2.Sobel(img, -1, 1, 0, ksize=3) # 只計算x方向
sobely = cv2.Sobel(img, -1, 0, 1, ksize=3) # 只計算y方向
# 【2】Laplacian算子
laplacian = cv2.Laplacian(img, -1) # 使用Laplacian算子
#【3】Scharr算子
scharr = cv2.Scharr(src, ddepth, dx, dy, dst=None, scale=None, delta=None, borderType=None, /)
(2)應用實例:
import cv2
def scharr_demo(image):
grad_x = cv2.Scharr(image, cv2.CV_32F, 1, 0) # 採用Scharr邊緣更突出
grad_y = cv2.Scharr(image, cv2.CV_32F, 0, 1)
gradx = cv2.convertScaleAbs(grad_x) # 由於算完的圖像有正有負,所以對其取絕對值
grady = cv2.convertScaleAbs(grad_y)
# 計算兩個圖像的權值和,dst = src1*alpha + src2*beta + gamma
gradxy = cv2.addWeighted(gradx, 0.5, grady, 0.5, 0)
cv2.imshow("gradx", gradx)
cv2.imshow("grady", grady)
cv2.imshow("gradient", gradxy)
src = cv2.imread("2.jpg")
cv2.imshow("lena", src)
scharr_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()
27.角點檢測:
(1)函數格式:
# 【1】harris角點檢測
cv.cornerHarris(img,blocksize,ksize,k)
參數:
img:圖片
blocksize:角點檢測區域的大小
ksize:sobel求導中使用的窗口的大小
k:取值參數
# 【2】Fast檢測器
cv.FastFeatureDetector_create([, threshold[, nonmaxSuppression[, type]]])
# 【3】繪製重要點
cv2.drawKeypoints(image,keypoints,outImage[,color[,flags]])
(2)應用實例:
# 【1】
import cv2 as cv
import numpy as np
img = cv.imread('1.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
dst = cv.cornerHarris(gray,2,3,0.04)
img[dst>0.01*dst.max()] = [0,0,255]
cv.imshow('res',img)
cv.waitKey(0)
# 【2】
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('1.jpg',0)
fast=cv2.FastFeatureDetector_create(threshold=20,nonmaxSuppression=True,type=cv2.FAST_FEATURE_DETECTOR_TYPE_9_16) #獲取FAST角點探測器
kp=fast.detect(img,None) #描述符
img = cv2.drawKeypoints(img,kp,img,color=(255,0,0)) #畫到img上面
print ("Threshold: ", fast.getThreshold()) #輸出閾值
print ("nonmaxSuppression: ", fast.getNonmaxSuppression())#是否使用非極大值抑制
print ("Total Keypoints with nonmaxSuppression: ", len(kp))#特徵點個數
cv2.imshow('sp',img)
cv2.waitKey(0)
28.圖像通道分離與合併:
# 【1】圖像通道分離
b, g, r = cv2.split(img)
# 【2】圖像通道合併
merge = cv2.merge([b, g, r])
29.圖像算術運算:
# 【1】加
dst = cv2.add(m1, m2)
# 【2】減
dst = cv2.subtract(m1, m2)
# 【3】乘
dst = cv2.multiply(m1, m2)
# 【4】除
dst = cv2.divide(m1, m2)
30.像素的均質和方差:
# 【1】均值
M1 = cv2.mean(img)
# 【2】均值和方差
M1, dev1 = cv2.meanStdDev(img)
31.漫水填充:
(1)函數格式:
def floodFill(image, mask, seedPoint, newVal, loDiff=None, upDiff=None, flags=None)
參數:
image:原圖像
mask:掩碼,單通道8位圖像,比image的高度多2個像素,寬度多2個像素。
seedPoint:起始點(原像素點,相當於鼠標點擊的那個像素點)
newVal:在重繪區域像素的新值(RBG值,相當於上圖指定的紅色)
loDiff:像素值的下限差值(最多比原像素點低多少)
upDiff:像素值的上限差值(最多比原像素點高多少)
Flag:
FLOODFILL_FIXED_RANGE:改變圖像,泛洪填充
FLOODFILL_MASK_ONLY:不改變圖像,只填充遮罩層本身,忽略新的顏色值參數
(2)應用實例:
import cv2
import numpy as np
def fill_color_demo(img):
copyImg = img.copy()
h, w = img.shape[:2]
mask = np.zeros([h + 2, w + 2], np.uint8)
cv2.floodFill(copyImg, mask, (100, 200), (0, 255, 0), (100, 100, 100), (50, 50, 50), cv2.FLOODFILL_FIXED_RANGE)
cv2.imshow("fill_color_demo", copyImg)
def fill_binary_demo():
img2 = np.zeros([400, 400, 3], np.uint8)
img2[100:300, 100:300, :] = 255
mask = np.ones([402, 402], np.uint8)
mask[101:301, 101:301] = 0
cv2.floodFill(img2, mask, (200, 200), (0, 0, 255), cv2.FLOODFILL_MASK_ONLY)
cv2.imshow("fill_binary_demo", img2)
fill_binary_demo()
img = cv2.imread('2.jpg')
fill_color_demo(img)
cv2.waitKey(0)
cv2.destroyAllWindows()
32.K近鄰(KNN):
(1)函數格式:
# 【1】
knn = cv.ml.KNearest_create()
# 【2】
knn.train(trainData, cv.ml.ROW_SAMPLE, responses)
# 【3】
ret, results, neighbours ,dist = knn.findNearest(newcomer, 3)
(2)函數格式:
import numpy as np
import cv2
#讀取圖片轉爲灰度圖
img = cv2.imread('digits.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#把圖片分隔成5000個,每個20x20大小
cells = [np.hsplit(row,100) for row in np.vsplit(gray,50)]
#再轉成numpy數組
x = np.array(cells)
#一半用來訓練的數組,一半用來測試的數組
train = x[:, :50].reshape(-1, 400).astype(np.float32)
test = x[:, 50:100].reshape(-1, 400).astype(np.float32)
#創建訓練和測試的標籤
k = np.arange(10)
train_labels = np.repeat(k,250)[:,np.newaxis]
test_labels = train_labels.copy()
#創建一個K-Nearest Neighbour分類器,訓練數據,然後用測試數據測試它
knn = cv2.ml.KNearest_create()
knn.train(train,cv2.ml.ROW_SAMPLE,train_labels)
ret,result,neighbours,dist = knn.findNearest(test,k=5)
#最終檢查測試的精確度,比較結果,檢查哪些是錯誤的,最終輸出正確率
matches = result == test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0 / result.size
print(accuracy)
33.擬合:
(1)直線擬合:
1)函數格式:
line =cv.fitLine(nptest,cv.DIST_L2,0,0.01,0.01)
參數:
points :nparray類型的點集(一般的數列直接報錯),待擬合的點的座標
distType:有關距離的定義,可用最快最簡單的L2距離,就是常用的最小二乘法
param:一些距離計算類型(distType)中用到的參數,寫0系統會自動選用最優的參數。
reps和aeps:用於表示擬合直線所需要的徑向和角度精度,通常情況下兩個值均被設定爲0.01。
2)應用實例:
import cv2 as cv
import numpy as np
test =[(1,2),(2,4),(3,6)]
nptest=np.array(test)
line =cv.fitLine(nptest,cv.DIST_L2,0,0.01,0.01)
(2)橢圓擬合:
1)函數格式:
ellipse = cv2.fitEllipse(cnt)
2)應用實例:
rrt = cv2.fitEllipse(contours[i])
# 繪製擬合橢圓
cv2.ellipse(ellipse1, rrt,255, 2, cv2.LINE_AA)
x, y = rrt[0]
# 中心
cv2.circle(ellipse1, (np.int(x), np.int(y)), 4, 255, -1, 8, 0)
plt.subplot(2, 3, 6),plt.imshow(ellipse1)
34.圖像連通域:
(1)函數格式:
ret, labels = cv2.connectedComponents(gray_img, connectivity=None)
# connectivity 4或8,臨近像素爲周圍4像素或8像素
(2)應用舉例:
import cv2
import numpy as np
img = np.array([
[0, 255, 0, 0],
[0, 0, 0, 255],
[0, 0, 0, 255],
[255, 0, 0, 0]
], np.uint8)
_, labels = cv2.connectedComponents(img)
print(labels)
res = cv2.equalizeHist(cv2.convertScaleAbs(labels))
print(res)
35.骨架提取:
import os
import numpy as np
import cv2
import sys
im = cv2.imread("cvLetter.jpg", 0)
ret, im = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
skel = np.zeros(im.shape, np.uint8)
erode = np.zeros(im.shape, np.uint8)
temp = np.zeros(im.shape, np.uint8)
i = 0
while True:
cv2.imshow('im %d' % (i), im)
erode = cv2.erode(im, element)
temp = cv2.dilate(erode, element)
# 消失的像素是skeleton的一部分
temp = cv2.subtract(im, temp)
cv2.imshow('skeleton part %d' % (i,), temp)
skel = cv2.bitwise_or(skel, temp)
im = erode.copy()
if cv2.countNonZero(im) == 0:
break;
i += 1
cv2.imshow('Skeleton', skel)
cv2.waitKey()
代碼來自:https://blog.csdn.net/aipush/article/details/84840870
骨架提取原理請見:https://www.cnblogs.com/xianglan/archive/2011/01/01/1923779.html
# -*- coding: utf-8 -*-
import cv2
def VThin(image, array):
h, w = image.shape
NEXT = 1
for i in range(h):
for j in range(w):
if NEXT == 0:
NEXT = 1
else:
M = int(image[i, j - 1]) + int(image[i, j]) + int(image[i, j + 1]) if 0 < j < w - 1 else 1
if image[i, j] == 0 and M != 0:
a = [0] * 9
for k in range(3):
for l in range(3):
if -1 < (i - 1 + k) < h and -1 < (j - 1 + l) < w and image[i - 1 + k, j - 1 + l] == 255:
a[k * 3 + l] = 1
sum = a[0] * 1 + a[1] * 2 + a[2] * 4 + a[3] * 8 + a[5] * 16 + a[6] * 32 + a[7] * 64 + a[8] * 128
image[i, j] = array[sum] * 255
if array[sum] == 1:
NEXT = 0
return image
def HThin(image, array):
h, w = image.shape
NEXT = 1
for j in range(w):
for i in range(h):
if NEXT == 0:
NEXT = 1
else:
M = int(image[i - 1, j]) + int(image[i, j]) + int(image[i + 1, j]) if 0 < i < h - 1 else 1
if image[i, j] == 0 and M != 0:
a = [0] * 9
for k in range(3):
for l in range(3):
if -1 < (i - 1 + k) < h and -1 < (j - 1 + l) < w and image[i - 1 + k, j - 1 + l] == 255:
a[k * 3 + l] = 1
sum = a[0] * 1 + a[1] * 2 + a[2] * 4 + a[3] * 8 + a[5] * 16 + a[6] * 32 + a[7] * 64 + a[8] * 128
image[i, j] = array[sum] * 255
if array[sum] == 1:
NEXT = 0
return image
def Xihua(image, array, num=10):
for i in range(num):
VThin(image, array)
HThin(image, array)
return image
def main():
# 映射表
array = [0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, \
1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, \
0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, \
1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, \
1, 1, 0, 0, 1, 1, 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, \
1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, \
1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, \
0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, \
1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, \
1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0]
# 讀取灰度圖片,並顯示
img = cv2.imread("cvLetter.jpg", 0) # 直接讀爲灰度圖像
cv2.imshow('image', img)
gaussian_img = cv2.GaussianBlur(img, (5, 5), 5)
kernel3 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dilate_img = cv2.dilate(gaussian_img, kernel3)
binary_img = cv2.adaptiveThreshold(dilate_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,7, 5)
cv2.imshow('binary', binary_img)
xihua_img = Xihua(binary_img, array)
cv2.imshow('xihua', xihua_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
main()
36.SVM:
(1)函數格式:
https://www.cnblogs.com/xixixing/p/12377090.html
svm = cv.ml.SVM_create()
# 設置核函數:LINEAR/POLY/RBF/SIGMOID
svm.setKernel(cv.ml.SVM_LINEAR)
# 設置迭代終止條件,默認:TermCriteria( TermCriteria::MAX_ITER + TermCriteria::EPS, 1000, FLT_EPSILON )
setTermCriteria()
# 指定SVM的類型:C_SVC/NU_SVC/ONE_CLASS/EPS_SVR/NU_SVR
svm.setType(cv.ml.SVM_C_SVC)
# 核函數相關:適用類型:SVM::POLY, SVM::RBF, SVM::SIGMOID or SVM::CHI2
svm.setGamma(5.383)
# 核函數相關:coef0(默認0)適用類型:SVM::POLY,SVM::SIGMOID
setCoef0()
# 核函數相關:degree(默認0)適用類型:SVM::POLY
setDegree()
# 優化相關:C(默認0)適用類型:SVM::C_SVC, SVM::EPS_SVR ,SVM::NU_SVR
svm.setC(2.67)
# 優化相關:nu(默認0)適用類型:SVM::NU_SVC, SVM::ONE_CLASS,SVM::NU_SVR
setNu()
# 優化相關:epsilon(默認0)適用類型:SVM::EPS_SVR
setP()
(2)應用實例:
import cv2 as cv
import numpy as np
SZ=20
# Number of bins
bin_n = 16
affine_flags = cv.WARP_INVERSE_MAP|cv.INTER_LINEAR
def deskew(img):
m = cv.moments(img)
if abs(m['mu02']) < 1e-2:
return img.copy()
skew = m['mu11']/m['mu02']
M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])
img = cv.warpAffine(img,M,(SZ, SZ),flags=affine_flags)
return img
def hog(img):
gx = cv.Sobel(img, cv.CV_32F, 1, 0)
gy = cv.Sobel(img, cv.CV_32F, 0, 1)
mag, ang = cv.cartToPolar(gx, gy)
bins = np.int32(bin_n*ang/(2*np.pi)) # quantizing binvalues in (0...16)
bin_cells = bins[:10,:10], bins[10:,:10], bins[:10,10:], bins[10:,10:]
mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
hist = np.hstack(hists) # hist is a 64 bit vector
return hist
img = cv.imread('digits.png',0)
cells = [np.hsplit(row,100) for row in np.vsplit(img,50)]
# 前一半是訓練數據,其餘是測試數據
train_cells = [ i[:50] for i in cells ]
test_cells = [ i[50:] for i in cells]
deskewed = [list(map(deskew,row)) for row in train_cells]
hogdata = [list(map(hog,row)) for row in deskewed]
trainData = np.float32(hogdata).reshape(-1,64)
responses = np.repeat(np.arange(10),250)[:,np.newaxis]
svm = cv.ml.SVM_create()
svm.setKernel(cv.ml.SVM_LINEAR)
svm.setType(cv.ml.SVM_C_SVC)
svm.setC(2.67)
svm.setGamma(5.383)
svm.train(trainData, cv.ml.ROW_SAMPLE, responses)
svm.save('svm_data.dat')
deskewed = [list(map(deskew,row)) for row in test_cells]
hogdata = [list(map(hog,row)) for row in deskewed]
testData = np.float32(hogdata).reshape(-1,bin_n*4)
result = svm.predict(testData)[1]
mask = result==responses
correct = np.count_nonzero(mask)
print(correct*100.0/result.size)