前言
歡迎來到我的博客
個人主頁:北嶺敲鍵盤的荒漠貓-CSDN博客
?本文整理python的OpenCV模塊的關鍵知識點
爭取用最短的時間入門OpenCV
并且做到筆記功能直接復制使用
OpenCV簡介
不浪費時間的介紹:
就是類似于ps操作圖片。
至于為什么不直接用ps,因為只有程序能完成ps的操作,這樣才能完全自動化2小時不間斷的執行一些程序,總不能執行到一定地方要等你人為的在ps中做好圖片再來執行程序吧。
功能點羅列:
畫圖,圖片高斯模糊,腐蝕膨脹等處理,開啟攝像頭。
最基本的使用
導入模塊:import cv2
方法 | 作用 |
---|---|
cv2.getVersionString() | 返回OpenCV的版本 |
cv2.imread(文件地址,圖片灰彩類型) | 讀取文件,用于實例化對象 灰彩類型:(可以不寫) cv2.IMREAD_COLOR讀入彩色圖像cv2.IMREAD_GRAYSCALE讀入灰色圖像 |
對象.shape | 返回圖片的大小(像素) |
cv2.imshow(窗口名,圖片對象) | 返回個窗口用于展示這個圖片 |
cv2.waitKey(自動關閉時間) | 窗口不自動關閉,知道按下任意鍵或者到規定時間(時間為微秒) 返回他按得鍵的代號數字 到時間返回-1 |
cv2.imwrite(保存路徑和文件名,保存的圖片) | 保存編輯的圖片 |
注意:
這個庫不支持任何中文!!!!!
不管是圖片文件命名還是窗口等
一律別用中文!!!!!!!
(至少我的版本不支持任何中文)
案例演示:
import cv2#導入庫
print(cv2.getVersionString())#返回版本號
image=cv2.imread("konglong.jpg")#導入圖片,實例化
print(image.shape)#返回圖片的大小和通道cv2.imshow("阿薩德",image)#展示圖片
cv2.waitKey(1000)#設置暫停
cv2.imwrite("okok.jpg",image)#保存圖片
結果:
打印信息
保存okok圖片
展示圖片(代碼中用中文做窗口所以會亂碼)
?視頻的打開方式
我們視頻有兩種:攝像頭,視頻文件
用到的函數:
讀取視頻或攝像頭:cv2.VideoCapture(視頻或者攝像頭的指針)
返回視頻讀取的照片:cap.read()
開啟攝像頭
思路:原理就是對這攝像頭一遍遍截圖。然后我們不斷的刷新顯示的圖片。
代碼如下:
import cv2#導入庫
cap=cv2.VideoCapture(0)#讀取攝像頭
while True:#循環valu,video=cap.read()#讀取攝像頭內容show=cv2.imshow("video",video)#展示攝像頭key=cv2.waitKey(1)#設置等待0.001秒刷新一次print(key)if key!=-1:#如果不是到時間刷新的視頻就退出視頻break
結果如下:
?按下別的鍵就關閉了。(字母有時候不行,數字或者特殊按鍵相對靠譜點)
視頻打開方式
代碼:
import cv2#導入庫
cap=cv2.VideoCapture("bingdu.mp4")
while True:valu,video=cap.read()show=cv2.imshow("video",video)key=cv2.waitKey(1)print(key)if key!=-1:break
基本一樣不截圖了
灰度圖獲取與處理
介紹:OpenCV儲存圖片實際上是儲存三原色的三張圖片,最后整合在一起。采用bgr圖像。
灰度加權平均:
cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
展示隔色彩圖像:
cv2.imshow("blue",image[:,:,0])
cv2.imshow("green",image[:,:,1])
cv2.imshow("red",image[:,:,2])
用法演示:(圖片太大不展示效果了)
import cv2
image=cv2.imread("konglong.jpg")
cv2.imshow("blue",image[:,:,0])
cv2.imshow("green",image[:,:,1])
cv2.imshow("red",image[:,:,2])
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv2.imshow("gray",gray)
cv2.waitKey()
裁剪圖像
crop=image[y軸開始裁剪位置:結束位置,x軸開始裁剪位置:結束位置]
水平為x,垂直為y
案例演示:
import cv2
image=cv2.imread("konglong.jpg")
print(image.shape)
y,h,x,w=100,300,100,600
crop=image[y:h,x:w]
cv2.imshow("crop",crop)
cv2.waitKey()
圖形繪制
可用于標記識別的物品
(注意,所有的粗細參數輸入負數后就是填充圖像)
繪制直線
cv2.line(圖片, 起點坐標, 終點坐標, 顏色, 粗細)
案例演示
import cv2
image=cv2.imread("okok.jpg")
cv2.line(image,(0,0),(700,600),(255,45,65),4)
cv2.imshow("image",image)
cv2.waitKey()
效果演示:
繪制方形
cv2.rectangle(圖片, 起點坐標, 終點坐標, 顏色, 粗細)
案例演示
import cv2
image=cv2.imread("okok.jpg")
cv2.rectangle(image,(309,310),(344,352),(255,45,65),4)
cv2.imshow("image",image)
cv2.waitKey()
繪制圓形
cv2.circle(image,原點坐標,半徑,顏色,粗細)
案例演示:
import cv2
image=cv2.imread("okok.jpg")
cv2.circle(image,(329,329),30,(255,45,65),4)
cv2.imshow("image",image)
cv2.waitKey()
?橢圓繪制
cv2.ellipse(圖片, 中心點坐標, 橫縱軸長度(元組), 旋轉角度, 起始角度, 結束角度, 顏色, 粗細)
案例演示:
import cv2
image=cv2.imread("okok.jpg")
cv2.ellipse(image, (256, 256), (100, 50), 60, 0, 360, (0, 255, 0), -1)
cv2.imshow("image",image)
cv2.waitKey()
繪制文字
cv2.putText(圖片, 文字, 位置, 字體, 文字大小, 顏色, 粗細)
案例演示:
import cv2
image=cv2.imread("okok.jpg")
cv2.putText(image, "how cool am i!", (250, 350), cv2.FONT_HERSHEY_SIMPLEX, 2, (65,54,87), 2)
cv2.imshow("image",image)
cv2.waitKey()
噪點處理
噪點描述:拍攝時信號傳輸收到干擾產生的雜色,如下:
噪點處理,其實就是讓他變模糊,模糊之后邊界就會不明顯。但是也會影響一定的畫面。
所以一般情況下,是對圖像的局部噪點嚴重的區域進行區域內的噪點處理。
注意下面的核必須是奇數。
高斯模糊
cv2.GaussianBlur(圖像,高斯核,sigmaX,sigmaY,邊界樣式)
x與y差越大越模糊,0的話就是自行計算
實際上一般可以用下面形式進行使用
cv2.GaussianBlur(image,(5,5),0)
中值濾過(像素排序取中值平滑處理)
cv2.medianBlur(圖片,核)
案例演示
import cv2
image=cv2.imread("zaodian.jpeg")
cv2.imshow("image",image)
gauss=cv2.GaussianBlur(image,(5,5),0,11)
cv2.imshow("gauss",gauss)
median=cv2.medianBlur(image,5)
cv2.imshow("median",median)
cv2.waitKey()
效果演示
圖片特征提取
(但是OpenCV提取圖像特征的水平有限,如果需要特別的精準可以嘗試別的庫)
提取圖片的特征,比如說轉角,邊緣,紋理啥的。
提取思路:先把圖像給轉化為灰度圖,然后在灰度圖中匹配轉角這類的特征。
函數:
cv2.cvtColor(圖片,cv2.COLOR_BGR2GRAY) #灰度處理
cv2.goodFeaturesToTrack(圖片,最大特征數,點的質量,特征最小的距離)
.ravel()#點的坐標
案例演示
import cv2
image=cv2.imread("okok.jpg")
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
corners=cv2.goodFeaturesToTrack(gray,500,0.1,10)
for corner in corners:x,y=corner.ravel()cv2.circle(image,(int(x),int(y)),2,(255,0,255),-1)
cv2.imshow("corners",image)
cv2.waitKey()
其實這些特征提取也不是特別的精準,看圖中的特征點也能看出來,這些特征點也不足以準確的識別這個畫面。
圖片匹配
原理:
也是把指定的圖片轉化為灰度圖,然后找特征點,之后在指定的圖片中匹配有沒有相似的特征點。
缺點:
對圖片的大小敏感。也就是說我們給的圖片距離鏡頭20m,但是在指定的圖片中,這個圖片在鏡頭50m的地方,就會因為大小不同而匹配不到。
解決思路:
可以改變圖像的大小進行多次匹配,或者減少匹配的精度要求(誤判多)。
(用到了numpy模塊)
函數
灰度處理:cv2.cvtColor(圖片,cv2.COLOR_BGR2GRAY)
匹配圖像:cv2.matchTemplate(gray_video, target, cv2.TM_CCOEFF_NORMED)
獲取坐標:numpy.where(match >= 匹配相似度)
案例演示
(我寫的這個識別度不是很高,不過能識別基本的功能,有點人工智障)
調用攝像頭實時識別書本上的java。
代碼案例
import cv2
import numpy as np
image=cv2.imread("java.jpg")
video=cv2.VideoCapture(0)
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
x1,y1=617,608
x2,y2=967,734
target=gray[y1:y2,x1:x2]
cv2.imshow("okk",target)
h,w=target.shape[0:2]
print("{},{}".format(h,w))
a=1
while True:#循環valu,video1=video.read()#讀取攝像頭內容gray_video=cv2.cvtColor(video1,cv2.COLOR_BGR2GRAY)if a==1:a=2cv2.imshow("okkk",gray_video)match = cv2.matchTemplate(gray_video, target, cv2.TM_CCOEFF_NORMED)place = np.where(match >= 0.9)print(place)for p in zip(*place[::-1]):x_1, y_1 = p[0], p[1]x_2, y_2 = x_1 + w, y_1 + hprint(x_1,x_2)cv2.rectangle(video1,(x_1, y_2),(x_2, y_2),(156, 124, 21), 1)show=cv2.imshow("video",video1)#展示攝像頭key=cv2.waitKey(1)#設置等待0.001秒刷新一次if key!=-1:#如果不是到時間刷新的視頻就退出視頻break
效果演示
嗯人工智障,識別條件特別苛刻。
不過也算是能夠完成實時識別的功能了。
圖像梯度算法
簡介一下圖像梯度:
圖像梯度就像地理地圖的等高線一樣。
給我們分辨一個區域的圖像像素變化的強度,如果他變化強度比較大,那么他大概率是圖形的邊緣。可以利用圖像的梯度來分辨圖像中的不同的物體。
拉普拉斯算子
作用:利用梯度的方法檢測圖像邊緣,輪廓以及紋理。
函數:
常用寫法:cv2.Laplacian(圖片,cv2.CV_64F)
完整寫法:cv2.Laplacian(image, dest, ddepth, ksize, scale, delta, borderType)
image是輸入圖像,dest是輸出圖像,ddepth是輸出圖像的深度,ksize是卷積核的大小,scale是拉普拉斯算子的系數
案例演示:
import cv2
image=cv2.imread("java.jpg")
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
laplacian=cv2.Laplacian(gray,cv2.CV_64F)
cv2.imshow("yuantu",image)
cv2.imshow("suanfa",laplacian)
cv2.waitKey()
效果演示:
?canny算子
函數:
cv2.Canny(gray,邊緣1,邊緣2)
原理:
像素變化強度大于邊緣2被判定為是邊界,小于邊界1被判定為不是邊界。在兩者之間的區域根據已經判斷的區域進行判斷。
源碼如下:
import cv2
image=cv2.imread("java.jpg")
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
canny=cv2.Canny(gray,100,200)
canny2=cv2.Canny(gray,50,100)
cv2.imshow("yuantu",image)
cv2.imshow("canny",canny)
cv2.imshow("canny2",canny2)
cv2.waitKey()
效果演示:
好處就是自己能規定他判斷的嚴格程度。
閾值算法(二值化)
普通算法
描述:眾所周知,我們世界的顏色并不是絕對的黑白,我們由黑白之間可以配出很多種灰色。
我們就可以用這個原理來把這些灰色絕對化。滿足某個值的就變成黑色,不滿足的就是白色。
這樣就可以識別一些黑暗環境中的文字或者物品。
(但也別指望太準,要是拿個你自己都分辨不出來的圖片,用這個也不容易。。。)
函數
cv2.threshold(圖片,閾值,最大灰度,處理方法)
本案例用的函數:cv2.threshold(gray,100,255,cv2.THRESH_BINARY)
(因為這張照片環境明堂堂的。。。)
案例演示
import cv2
image=cv2.imread("java.jpg")
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,binary=cv2.threshold(gray,100,255,cv2.THRESH_BINARY)
cv2.imshow("binary",binary)
cv2.waitKey()
效果演示
分區二值化算法
OpenCV有內置的分區二值化算法,自動計算這個小區域的閾值,并設定合適的閾值。
函數
函數:(案例)
cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,115,1)該函數有以下參數:src: 要二值化的原始圖像。maxval: 閾值的最大值。adaptiveMethod: 用于計算閾值的方法。有兩個選項可供選擇:cv2.ADAPTIVE_THRESH_MEAN_C和cv2.ADAPTIVE_THRESH_GAUSSIAN_C。推薦使用默認的cv2.ADAPTIVE_THRESH_GAUSSIAN_C。thresholdType: 閾值類型。可以是cv2.THRESH_BINARY或cv2.THRESH_BINARY_INV。推薦使用默認的cv2.THRESH_BINARY。blockSize: 每個局部區域的大小,用來計算局部閾值。C: 從平均值或加權平均值中減去的常數。該參數在計算局部閾值時起到調整閾值的作用。
案例演示
import cv2
image=cv2.imread("java.jpg")
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
binary_adaptive=cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,115,1)
cv2.imshow("binary",binary_adaptive)
cv2.waitKey()
結果演示
可以看到,明顯的比自己寫的那個好用。
大金算法
算法原理:找兩個最大的值,然后取兩個值的中心。讓黑白差異最大化。
函數
cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
好處
完全不用咱們自己設置閾值,他自己就可以設置的明明白白的。
但是也有缺點,不如自己設置的完美,有時候可能不是很好用。
案例演示
import cv2
image=cv2.imread("java.jpg")
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret1,binary_otsu=cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow("binary",binary_otsu)
cv2.waitKey()
效果演示
腐蝕與膨脹
腐蝕:就是給圖像變瘦一點(減少白色)
膨脹:相反,給圖像變胖一點(增加白色)
作用:可以處理圖像邊緣,放大或者縮小圖像的細節。
函數
他們都需要創建一個核
np.ones((5, 5), np.uint8)
膨脹與腐蝕
cv2.erode(圖像, kernel) # 腐蝕
cv2.dilate(圖像, kernel) # 膨脹
案例演示:
import cv2
import numpy as np
image=cv2.imread("java.jpg")
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret1,binary_otsu=cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((5, 5), np.uint8)
erosion = cv2.erode(binary_otsu, kernel) # 腐蝕
dilate = cv2.dilate(binary_otsu, kernel) # 膨脹
cv2.imshow("binary",binary_otsu)
cv2.imshow("er",erosion)
cv2.imshow("di",dilate)
cv2.waitKey()
效果演示:
腐蝕
膨脹
?這里看到,明明是腐蝕但是感覺像是做出膨脹的效果,這是因為這個是腐蝕白色。所以對于黑色來說是膨脹了。
總結
OK,這些就是OpenCV的基礎了。
他還有很多深入的算法,需要自己挖掘。
掌握了這些就能實現一些基本的功能了。