計算機視覺
第七章 綜合案例
一、利用OpenCV實現圖像校正
1. 任務描述
- 我們對圖像中的目標進行分析和檢測時,目標往往具有一定的傾斜角度,自然條件下拍攝的圖像,完全平正是很少的。因此,需要將傾斜的目標“扶正”的過程就叫做圖像矯正。該案例中使用的原始圖像如下:
2. 代碼
# 圖像矯正示例
import cv2
import numpy as np
import math
im = cv2.imread("../data/paper.jpg")
cv2.imshow("im", im)
# 灰度化
im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
# 邊緣提取
# sobel 效果不好,不采用
# sobel = cv2.Sobel(im_gray, cv2.CV_64F, 1, 1, ksize=5)
# cv2.imshow("sobel", sobel)
# Laplacian 效果不好,不采用
# lap = cv2.Laplacian(im_gray, cv2.CV_64F)
# cv2.imshow("Laplacian", lap)
# 模糊化:去掉過細的細節
blurred = cv2.GaussianBlur(im_gray, (5, 5), 0)
# 膨脹:將過細的細節合並
dilate = cv2.dilate(blurred, (3, 3))
# canny
canny = cv2.Canny(dilate, 30, 120)
# cv2.imshow("canny", canny)
# 輪廓檢測
cnts, hie = cv2.findContours(canny.copy(), # 原始圖像
cv2.RETR_EXTERNAL, # 只檢測外輪廓
cv2.CHAIN_APPROX_SIMPLE) # 只保留輪廓的終點坐標
# 繪制輪廓
im_cnt = cv2.drawContours(im, cnts, -1, (0, 0, 255), 2)
cv2.imshow("im_cnt", im_cnt)
docCnt = None
# 計算輪廓面積,排序
if len(cnts) > 0:
cnts = sorted(cnts, # 可迭代對象
key=cv2.contourArea, # 排序依據,計算輪廓面積,根據面積排序
reverse=True) # 逆序排列
for c in cnts: # 遍歷排序後的每個輪廓
peri = cv2.arcLength(c, True) # 計算封閉輪廓周長
approx = cv2.approxPolyDP(c, 0.02*peri, True) # 多邊形擬合
# 擬合出的第一個四邊形認為是紙張的輪廓
if len(approx) == 4:
docCnt = approx
break
# 繪制找到的四邊形的交點
points = []
for peak in docCnt:
peak = peak[0] # 取出坐標
# 繪制角點
cv2.circle(im, # 繪制的圖像
tuple(peak), 10, # 圓心,半徑
(0, 0, 255), 2) # 繪制圓形線條顏色和粗細
points.append(peak) # 坐標添加到列表
cv2.imshow("im_point", im)
# 矯正
# 原紙張逆時針方向四個角點
src = np.float32([points[0], points[1], points[2], points[3]])
dst = np.float32([[0, 0], [0, 488], [337, 488], [337, 0]])
m = cv2.getPerspectiveTransform(src, dst) # 生成透視矩陣
result = cv2.warpPerspective(im_gray.copy(), m, (337,488)) # 透視變換
cv2.imshow("result", result)
cv2.waitKey() # 等待用戶按某個按鍵
cv2.destroyAllWindows() # 銷毀所有創建的窗口
二、利用OpenCV檢測芯片瑕疵
1. 任務描述
- 利用圖像技術,檢測出芯片鍍盤區域瑕疵。樣本圖像中,粉紅色區域為鍍盤區域,鍍盤內部空洞為瑕疵區域,利用圖像技術檢測鍍盤是否存在瑕疵,如果存在則將瑕疵區域標記出來。
2. 思路
- 將原始圖像讀取出來,做灰度化處理
- 經過灰度化處理以後發現,目標區域的顏色要淺一些,所以做了二值化處理
- 經過二值化處理以後,做了實心的填充,實心化填充之前要取出輪廓
- 實心化填充以後,有瑕疵和沒有瑕疵,兩張圖片的對比就很明顯了,所以就做了圖像的減法
- 圖像減法是求出兩幅圖像之間的差異,所以就把瑕疵給找了出來
- 經過觀察發現,瑕疵區域有一些很小的瑕疵點,沒有連接在一起,所以又做了閉運算,先膨脹後腐蝕,把原本沒有連在一起的區域連在一起,膨脹以後瑕疵區域會變大,所以又做了腐蝕,把瑕疵區域還原成原來的大小
- 再把瑕疵的輪廓找出來,繪制最小外接圓形,再在原始圖像上繪制一個彩色的圓形,這樣瑕疵所在的位置就很明顯了
- 最後一步,計算瑕疵的面積,瑕疵面積這裡可以使用輪廓的面積,使用外接圓的面積,面積大於一定的數值就認為它有瑕疵
3. 代碼
# 利用圖像技術實現芯片瑕疵檢測
import cv2
import numpy as np
import math
im = cv2.imread("../data/CPU3.png") # 讀取彩色圖像
cv2.imshow("im", im)
# 灰度化
im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
cv2.imshow("im_gray", im_gray)
# 二值化
ret, im_bin = cv2.threshold(im_gray, 162, 255, cv2.THRESH_BINARY)
cv2.imshow("im_bin", im_bin)
# 提取輪廓,實心化填充
cnts, hie = cv2.findContours(im_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
mask = np.zeros(im_bin.shape, np.uint8) # 創建值全為0的矩陣,形狀和im_bin一致
im_fill = cv2.drawContours(mask, cnts, -1, (255, 0, 0), -1) # 繪制輪廓並進行實心填充
cv2.imshow("im_fill", im_fill)
# 圖像減法,找出瑕疵區域
im_sub = cv2.subtract(im_fill, im_bin)
cv2.imshow("im_sub", im_sub)
# 圖像的閉運算(先膨脹後腐蝕),將離散的瑕疵點合並在一起
k = np.ones((10, 10), np.uint8)
im_close = cv2.morphologyEx(im_sub, cv2.MORPH_CLOSE, k, iterations=3)
cv2.imshow("im_close", im_close)
# 提取瑕疵區域輪廓,繪制最小外接圓形
cnts, hie = cv2.findContours(im_close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# 產生最小外接圓數據
(x, y), radius = cv2.minEnclosingCircle(cnts[1])
center = (int(x), int(y))
radius = int(radius)
cv2.circle(im_close, center, radius, (255, 0, 0), 2) # 繪制瑕疵的最小外接圓形
cv2.imshow("im_circle", im_close)
# 在原始圖像上繪制瑕疵
cv2.circle(im, center, radius, (0, 0, 255), 2)
cv2.imshow("im_result", im)
# 計算外接圓形的面積
area = math.pi * radius * radius
print("area:", area)
if area > 12:
print("鍍盤表明有瑕疵")
cv2.waitKey() # 等待用戶按某個按鍵
cv2.destroyAllWindows() # 銷毀所有創建的窗口
第八章 視頻基本處理
一、讀取攝像頭
# 從攝像頭讀取圖像並播放
import cv2
# 實例化VideoCapture對象,參數0表示第一個攝像頭
cap = cv2.VideoCapture(0)
while cap.isOpened(): # 攝像頭處於打開狀態
ret, frame = cap.read() # 捕獲幀
# 每次讀取幀後顯示在同一個窗體裡,這樣連續的窗體顯示就形成視頻
cv2.imshow("frame", frame)
c = cv2.waitKey(1) # 等待1毫秒,等待用戶敲擊按鍵
if c == 27: # ESC鍵
break
cap.release() # 釋放視頻設備資源
cv2.destroyAllWindows()
二、播放視頻文件
# 讀取視頻文件並播放
import cv2
# 創建對象,並指定打開的視頻文件路徑
cap = cv2.VideoCapture("D:\\Alex\\Music\\MV\\2750443843.mp4")
while cap.isOpened():
ret, frame = cap.read() # 讀取幀
cv2.imshow("frame", frame) # 顯示
c = cv2.waitKey(25) # 等待用戶敲擊按鍵
if c == 27:
break
cap.release()
cv2.destroyAllWindows()
三、捕獲並保存視頻
# 錄制視頻文件
# 兩個過程:讀取、寫入文件
import cv2
cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc("I", "4", "2", "0") # 編解碼4字標記值
out = cv2.VideoWriter("output.avi", # 視頻文件名稱
fourcc, # 編解碼格式
20, # 幀速度
(640,480)) # 分辨率
while cap.isOpened():
ret, frame = cap.read() # 捕獲幀
if ret == True:
out.write(frame) # 寫入幀
cv2.imshow("frame", frame) # 顯示幀
if cv2.waitKey(1) == 27: # ESC鍵
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
第九章 圖像預處理在AI中的應用
- 圖像預處理的目的,是讓圖像數據更適合AI模型進行處理,例如調整大小、顏色
- 通過圖像預處理技術,實現數據集的擴充,這種方法稱為數據增強。數據增強主要方法有:縮放,拉伸,加入噪點,翻轉,旋轉,平移,剪切,對比度調整,通道變化。
一、圖像數據增強
二、純圖像技術的缺陷
- 到目前為止,我們使用的基本是純圖像技術,對圖像大小、顏色、形狀、輪廓、邊沿進行變換和處理,但這些技術都有一個共同的缺點,即無法理解圖像內容和場景,要實現這個目標,必須借助於深度學習技術。