該系列文章是講解Python OpenCV圖像處理知識,前期主要講解圖像入門、OpenCV基礎用法,中期講解圖像處理的各類算法,包括圖像銳化算子、圖像加強技術、圖像分割等,後期結合深度學習研究圖像識別、圖像分類應用。但願文章對您有所幫助,若是有不足之處,還請海涵~html
前面一篇文章介紹了MoviePy視頻編輯庫,實現視頻的自定義剪切和合並操做;這篇文章將詳細講解圖像量化及採樣處理,萬字長文吐血整理。同時,該部分知識均爲秀璋查閱資料撰寫整理,而且開設成了收費專欄,爲小寶賺點奶粉錢。固然若是您是學生或者經濟拮据,能夠私聊我給你每篇文章開白名單,或者轉發原文給你,更多的是但願您心甘情願的打賞及進步。一塊兒加油喔~python
該系列在github全部源代碼:git
前文參考:
[Python圖像處理] 一.圖像處理基礎知識及OpenCV入門函數
[Python圖像處理] 二.OpenCV+Numpy庫讀取與修改像素
[Python圖像處理] 三.獲取圖像屬性、興趣ROI區域及通道處理
[Python圖像處理] 四.圖像平滑之均值濾波、方框濾波、高斯濾波及中值濾波
[Python圖像處理] 五.圖像融合、加法運算及圖像類型轉換
[Python圖像處理] 六.圖像縮放、圖像旋轉、圖像翻轉與圖像平移
[Python圖像處理] 七.圖像閾值化處理及算法對比
[Python圖像處理] 八.圖像腐蝕與圖像膨脹
[Python圖像處理] 九.形態學之圖像開運算、閉運算、梯度運算
[Python圖像處理] 十.形態學之圖像頂帽運算和黑帽運算
[Python圖像處理] 十一.灰度直方圖概念及OpenCV繪製直方圖
[Python圖像處理] 十二.圖像幾何變換之圖像仿射變換、圖像透視變換和圖像校訂
[Python圖像處理] 十三.基於灰度三維圖的圖像頂帽運算和黑帽運算
[Python圖像處理] 十四.基於OpenCV和像素處理的圖像灰度化處理
[Python圖像處理] 十五.圖像的灰度線性變換
[Python圖像處理] 十六.圖像的灰度非線性變換之對數變換、伽馬變換
[Python圖像處理] 十七.圖像銳化與邊緣檢測之Roberts算子、Prewitt算子、Sobel算子和Laplacian算子
[Python圖像處理] 十八.圖像銳化與邊緣檢測之Scharr算子、Canny算子和LOG算子
[Python圖像處理] 十九.圖像分割之基於K-Means聚類的區域分割
[Python圖像處理] 二十.圖像量化處理和採樣處理及局部馬賽克特效
[Python圖像處理] 二十一.圖像金字塔之圖像向下取樣和向上取樣
[Python圖像處理] 二十二.Python圖像傅里葉變換原理及實現
[Python圖像處理] 二十三.傅里葉變換之高通濾波和低通濾波
[Python圖像處理] 二十四.圖像特效處理之毛玻璃、浮雕和油漆特效
[Python圖像處理] 二十五.圖像特效處理之素描、懷舊、光照、流年以及濾鏡特效
[Python圖像處理] 二十六.圖像分類原理及基於KNN、樸素貝葉斯算法的圖像分類案例
[Python圖像處理] 二十七.OpenGL入門及繪製基本圖形(一)
[Python圖像處理] 二十八.OpenCV快速實現人臉檢測及視頻中的人臉
[Python圖像處理] 二十九.MoviePy視頻編輯庫實現抖音短視頻剪切合並操做
github
文章目錄
圖像一般是天然界景物的客觀反映,並以照片形式或視頻記錄的介質連續保存,獲取圖像的目標是從感知的數據中產生數字圖像,所以須要把連續的圖像數據離散化,轉換爲數字化圖像,其工做主要包括兩方面——量化和採樣。數字化幅度值稱爲量化,數字化座標值稱爲採樣。本文主要講解圖像量化和採樣處理的概念,並經過Python和OpenCV實現這些功能。算法
一.圖像量化處理
1.概述
所謂量化(Quantization),就是將圖像像素點對應亮度的連續變化區間轉換爲單個特定值的過程,即將原始灰度圖像的空間座標幅度值離散化。量化等級越多,圖像層次越豐富,灰度分辨率越高,圖像的質量也越好;量化等級越少,圖像層次欠豐富,灰度分辨率越低,會出現圖像輪廓分層的現象,下降了圖像的質量。圖1是將圖像的連續灰度值轉換爲0至255的灰度級的過程。編程
若是量化等級爲2,則將使用兩種灰度級表示原始圖片的像素(0-255),灰度值小於128的取0,大於等於128的取128;若是量化等級爲4,則將使用四種灰度級表示原始圖片的像素,新圖像將分層爲四種顏色,0-64區間取0,64-128區間取64,128-192區間取128,192-255區間取192,依次類推。安全
圖2是對比不一樣量化等級的「Lena」圖。其中(a)的量化等級爲256,(b)的量化等級爲64,(c)的量化等級爲16,(d)的量化等級爲8,(e)的量化等級爲4,(f)的量化等級爲2。網絡
2.操做
下面講述Python圖像量化處理相關代碼操做。其核心流程是創建一張臨時圖片,接着循環遍歷原始圖像中全部像素點,判斷每一個像素點應該屬於的量化等級,最後將臨時圖像顯示。下列代碼將灰度圖像轉換爲兩種量化等級。函數
# -*- coding: utf-8 -*- # BY:Eastmount CSDN 2020-11-10 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('lena.png') #獲取圖像高度和寬度 height = img.shape[0] width = img.shape[1] #建立一幅圖像 new_img = np.zeros((height, width, 3), np.uint8) #圖像量化操做 量化等級爲2 for i in range(height): for j in range(width): for k in range(3): #對應BGR三份量 if img[i, j][k] < 128: gray = 0 else: gray = 128 new_img[i, j][k] = np.uint8(gray) #顯示圖像 cv2.imshow("src", img) cv2.imshow("Quantization", new_img) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
其輸出結果如圖3所示,它將灰度圖像劃分爲兩種量化等級。學習
下面的代碼分別比較了量化等級爲二、四、8的量化處理效果。
# -*- coding: utf-8 -*- # BY:Eastmount CSDN 2020-11-10 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('lena.png') #獲取圖像高度和寬度 height = img.shape[0] width = img.shape[1] #建立一幅圖像 new_img1 = np.zeros((height, width, 3), np.uint8) new_img2 = np.zeros((height, width, 3), np.uint8) new_img3 = np.zeros((height, width, 3), np.uint8) #圖像量化等級爲2的量化處理 for i in range(height): for j in range(width): for k in range(3): #對應BGR三份量 if img[i, j][k] < 128: gray = 0 else: gray = 128 new_img1[i, j][k] = np.uint8(gray) #圖像量化等級爲4的量化處理 for i in range(height): for j in range(width): for k in range(3): #對應BGR三份量 if img[i, j][k] < 64: gray = 0 elif img[i, j][k] < 128: gray = 64 elif img[i, j][k] < 192: gray = 128 else: gray = 192 new_img2[i, j][k] = np.uint8(gray) #圖像量化等級爲8的量化處理 for i in range(height): for j in range(width): for k in range(3): #對應BGR三份量 if img[i, j][k] < 32: gray = 0 elif img[i, j][k] < 64: gray = 32 elif img[i, j][k] < 96: gray = 64 elif img[i, j][k] < 128: gray = 96 elif img[i, j][k] < 160: gray = 128 elif img[i, j][k] < 192: gray = 160 elif img[i, j][k] < 224: gray = 192 else: gray = 224 new_img3[i, j][k] = np.uint8(gray) #用來正常顯示中文標籤 plt.rcParams['font.sans-serif']=['SimHei'] #顯示圖像 titles = ['(a) 原始圖像', '(b) 量化-L2', '(c) 量化-L4', '(d) 量化-L8'] images = [img, new_img1, new_img2, new_img3] for i in range(4): plt.subplot(2,2,i+1), plt.imshow(images[i], 'gray'), plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
輸出結果如圖4所示,該代碼調用matplotlib.pyplot庫繪製了四幅圖像,其中(a)表示原始圖像,(b)表示等級爲2的量化處理,(c)表示等級爲4的量化處理,(d)表示等級爲8的量化處理。
3.K-Means聚類量化處理
上一小節的量化處理是經過遍歷圖像中的全部像素點,進行灰度圖像的幅度值離散化處理。本小節補充一個基於K-Means聚類算法的量化處理過程,它可以將彩色圖像RGB像素點進行顏色分割和顏色量化。注意,在第十九篇文章時詳細介紹了K-Means聚類知識,本小節只是帶領讀者從新回顧下該方法。
# coding: utf-8 # BY:Eastmount CSDN 2020-11-10 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('nv.png') #圖像二維像素轉換爲一維 data = img.reshape((-1,3)) data = np.float32(data) #定義中心 (type,max_iter,epsilon) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) #設置標籤 flags = cv2.KMEANS_RANDOM_CENTERS #K-Means聚類 彙集成4類 compactness, labels, centers = cv2.kmeans(data, 4, None, criteria, 10, flags) #圖像轉換回uint8二維類型 centers = np.uint8(centers) res = centers[labels.flatten()] dst = res.reshape((img.shape)) #圖像轉換爲RGB顯示 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) dst = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB) #用來正常顯示中文標籤 plt.rcParams['font.sans-serif']=['SimHei'] #顯示圖像 titles = ['原始圖像', '聚類量化 K=4'] images = [img, dst] for i in range(2): plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray'), plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
輸出結果如圖5所示,它經過K-Means聚類算法將彩色人物圖像的灰度彙集成四種顏色。
二.圖像採樣處理
1.概述
圖像採樣(Image Sampling)處理是將一幅連續圖像在空間上分割成M×N個網格,每一個網格用一個亮度值或灰度值來表示,其示意圖如圖6所示。
圖像採樣的間隔越大,所得圖像像素數越少,空間分辨率越低,圖像質量越差,甚至出現馬賽克效應;相反,圖像採樣的間隔越小,所得圖像像素數越多,空間分辨率越高,圖像質量越好,但數據量會相應的增大。圖7展現了不一樣採樣間隔的「Lena」圖,其中圖(a)爲原始圖像,圖(b)爲128×128的圖像採樣效果,圖©爲64×64的圖像採樣效果,圖(d)爲32×32的圖像採樣效果,圖(e)爲16×16的圖像採樣效果,圖(f)爲8×8的圖像採樣效果。
數字圖像的質量很大程度上取決於量化和採樣中所採用的樣本數和灰度級。現實生活中的圖像,都須要通過離散化處理轉換成數字圖像,從而進行後續的計算機處理和圖像識別等操做。圖8展現了生活圖像轉換爲數字圖像的過程。
2.操做
下面講述Python圖像採樣處理相關代碼操做。其核心流程是創建一張臨時圖片,設置須要採樣的區域大小(如16×16),接着循環遍歷原始圖像中全部像素點,採樣區域內的像素點賦值相同(如左上角像素點的灰度值),最終實現圖像採樣處理。下列代碼是進行16×16採樣的過程。
# -*- coding: utf-8 -*- # BY:Eastmount CSDN 2020-11-10 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('lena.png') #獲取圖像高度和寬度 height = img.shape[0] width = img.shape[1] #採樣轉換成16*16區域 numHeight = int(height/16) numWidth = int(width/16) #建立一幅圖像 new_img = np.zeros((height, width, 3), np.uint8) #圖像循環採樣16*16區域 for i in range(16): #獲取Y座標 y = i*numHeight for j in range(16): #獲取X座標 x = j*numWidth #獲取填充顏色 左上角像素點 b = img[y, x][0] g = img[y, x][1] r = img[y, x][2] #循環設置小區域採樣 for n in range(numHeight): for m in range(numWidth): new_img[y+n, x+m][0] = np.uint8(b) new_img[y+n, x+m][1] = np.uint8(g) new_img[y+n, x+m][2] = np.uint8(r) #顯示圖像 cv2.imshow("src", img) cv2.imshow("Sampling", new_img) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
其輸出結果如圖8所示,它將灰度圖像採樣成16×16的區域。
一樣,能夠對彩色圖像進行採樣處理,下面的代碼將彩色風景圖像採樣處理成8×8的馬賽克區域。
# -*- coding: utf-8 -*- # BY:Eastmount CSDN 2020-11-10 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('scenery.png') #獲取圖像高度和寬度 height = img.shape[0] width = img.shape[1] #採樣轉換成8*8區域 numHeight = int(height/8) numwidth = int(width/8) #建立一幅圖像 new_img = np.zeros((height, width, 3), np.uint8) #圖像循環採樣8*8區域 for i in range(8): #獲取Y座標 y = i*numHeight for j in range(8): #獲取X座標 x = j*numwidth #獲取填充顏色 左上角像素點 b = img[y, x][0] g = img[y, x][1] r = img[y, x][2] #循環設置小區域採樣 for n in range(numHeight): for m in range(numwidth): new_img[y+n, x+m][0] = np.uint8(b) new_img[y+n, x+m][1] = np.uint8(g) new_img[y+n, x+m][2] = np.uint8(r) #顯示圖像 cv2.imshow("src", img) cv2.imshow("Sampling", new_img) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
其輸出結果如圖9所示,它將彩色風景圖像採樣成8×8的區域。
但上述代碼存在一個問題,當圖像的長度和寬度不能被採樣區域整除時,輸出圖像的最右邊和最下邊的區域沒有被採樣處理。這裏推薦讀者作個求餘運算,將不能整除部分的區域也進行相應的採樣處理。
3.局部馬賽克處理
前面講述的代碼是對整幅圖像進行採樣處理,那麼如何對圖像的局部區域進行馬賽克處理呢?下面的代碼就實現了該功能。當鼠標按下時,它可以給鼠標拖動的區域打上馬賽克,並按下「s」鍵保存圖像至本地。
# -- coding:utf-8 -- # BY:Eastmount CSDN 2020-11-10 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 im = cv2.imread('people.png', 1) #設置鼠標左鍵開啓 en = False #鼠標事件 def draw(event, x, y, flags, param): global en #鼠標左鍵按下開啓en值 if event==cv2.EVENT_LBUTTONDOWN: en = True #鼠標左鍵按下而且移動 elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_LBUTTONDOWN: #調用函數打馬賽克 if en: drawMask(y,x) #鼠標左鍵彈起結束操做 elif event==cv2.EVENT_LBUTTONUP: en = False #圖像局部採樣操做 def drawMask(x, y, size=10): #size*size採樣處理 m = int(x / size * size) n = int(y / size * size) print(m, n) #10*10區域設置爲同一像素值 for i in range(size): for j in range(size): im[m+i][n+j] = im[m][n] #打開對話框 cv2.namedWindow('image') #調用draw函數設置鼠標操做 cv2.setMouseCallback('image', draw) #循環處理 while(1): cv2.imshow('image', im) #按ESC鍵退出 if cv2.waitKey(10)&0xFF==27: break #按s鍵保存圖片 elif cv2.waitKey(10)&0xFF==115: cv2.imwrite('sava.png', im) #退出窗口 cv2.destroyAllWindows()
其輸出結果如圖10所示,它將人物的臉部進行馬賽克處理,按下S鍵保存圖片,按下ESC鍵退出。
三.圖像金字塔
前面講解的圖像採樣處理能夠下降圖像的大小,本小節將補充圖像金字塔知識,瞭解專門用於圖像向上採樣和向下採樣的pyrUp()和pyrDown()函數。
圖像金字塔是指由一組圖像且不一樣分別率的子圖集合,它是圖像多尺度表達的一種,以多分辨率來解釋圖像的結構,主要用於圖像的分割或壓縮。一幅圖像的金字塔是一系列以金字塔形狀排列的分辨率逐步下降,且來源於同一張原始圖的圖像集合。如圖11所示,它包括了四層圖像,將這一層一層的圖像比喻成金字塔。圖像金字塔能夠經過梯次向下採樣得到,直到達到某個終止條件才中止採樣,在向下採樣中,層級越高,則圖像越小,分辨率越低。
生成圖像金字塔主要包括兩種方式——向下取樣、向上取樣。在圖11中,將圖像G0轉換爲G一、G二、G3,圖像分辨率不斷下降的過程稱爲向下取樣;將G3轉換爲G二、G一、G0,圖像分辨率不斷增大的過程稱爲向上取樣。
1.圖像向下取樣
在圖像向下取樣中,使用最多的是高斯金字塔。它將對圖像Gi進行高斯核卷積,並刪除原圖中全部的偶數行和列,最終縮小圖像。其中,高斯核卷積運算就是對整幅圖像進行加權平均的過程,每個像素點的值,都由其自己和鄰域內的其餘像素值(權重不一樣)通過加權平均後獲得。常見的3×3和5×5高斯核以下:
高斯核卷積讓臨近中心的像素點具備更高的重要度,對周圍像素計算加權平均值,如圖12所示,其中心位置權重最高爲0.4。
顯而易見,原始圖像Gi具備M×N個像素,進行向下取樣以後,所獲得的圖像Gi+1具備M/2×N/2個像素,只有原圖的四分之一。經過對輸入的原始圖像不停迭代以上步驟就會獲得整個金字塔。注意,因爲每次向下取樣會刪除偶數行和列,因此它會不停地丟失圖像的信息。
在OpenCV中,向下取樣使用的函數爲pyrDown(),其原型以下所示:
- dst = pyrDown(src[, dst[, dstsize[, borderType]]])
– src表示輸入圖像,
– dst表示輸出圖像,和輸入圖像具備同樣的尺寸和類型
– dstsize表示輸出圖像的大小,默認值爲Size()
– borderType表示像素外推方法,詳見cv::bordertypes
向下取樣的代碼以下所示:
# -*- coding: utf-8 -*- # BY:Eastmount CSDN 2020-11-10 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('nv.png') #圖像向下取樣 r = cv2.pyrDown(img) #顯示圖像 cv2.imshow('original', img) cv2.imshow('PyrDown', r) cv2.waitKey() cv2.destroyAllWindows()
輸出結果如圖13所示,它將原始圖像壓縮成原圖的四分之一。
屢次向下取樣的代碼參考下列文件。
# -*- coding: utf-8 -*- # BY:Eastmount CSDN 2020-11-10 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('nv.png') #圖像向下取樣 r1 = cv2.pyrDown(img) r2 = cv2.pyrDown(r1) r3 = cv2.pyrDown(r2) #顯示圖像 cv2.imshow('original', img) cv2.imshow('PyrDown1', r1) cv2.imshow('PyrDown2', r2) cv2.imshow('PyrDown3', r3) cv2.waitKey() cv2.destroyAllWindows()
輸出結果如圖14所示,每次向下取樣均爲上次的四分之一,而且圖像的清晰度會下降。
2.圖像向上取樣
在圖像向上取樣是由小圖像不斷放圖像的過程。它將圖像在每一個方向上擴大爲原圖像的2倍,新增的行和列均用0來填充,並使用與「向下取樣」相同的卷積核乘以4,再與放大後的圖像進行卷積運算,以得到「新增像素」的新值。如圖15所示,它在原始像素4五、12三、8九、149之間各新增了一行和一列值爲0的像素。
注意,向上取樣放大後的圖像比原始圖像要模糊。同時,向上採樣和向下採樣不是互逆的操做,通過兩種操做後,是沒法恢復原始圖像的。
在OpenCV中,向上取樣使用的函數爲pyrUp(),其原型以下所示:
- dst = pyrUp(src[, dst[, dstsize[, borderType]]])
– src表示輸入圖像,
– dst表示輸出圖像,和輸入圖像具備同樣的尺寸和類型
– dstsize表示輸出圖像的大小,默認值爲Size()
– borderType表示像素外推方法,詳見cv::bordertypes
向上取樣的代碼以下所示:
# -*- coding: utf-8 -*- # BY:Eastmount CSDN 2020-11-10 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('lena.png') #圖像向上取樣 r = cv2.pyrUp(img) #顯示圖像 cv2.imshow('original', img) cv2.imshow('PyrUp', r) cv2.waitKey() cv2.destroyAllWindows()
輸出結果如圖16所示,它將原始圖像擴大爲原圖像的四倍,即向上一次取樣。
屢次向上取樣的代碼參考下列文件。
# -*- coding: utf-8 -*- import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('lena2.png') #圖像向上取樣 r1 = cv2.pyrUp(img) r2 = cv2.pyrUp(r1) r3 = cv2.pyrUp(r2) #顯示圖像 cv2.imshow('original', img) cv2.imshow('PyrUp1', r1) cv2.imshow('PyrUp2', r2) cv2.imshow('PyrUp3', r3) cv2.waitKey() cv2.destroyAllWindows()
輸出結果如圖17所示,每次向上取樣均爲上次圖像的四倍,但圖像的清晰度會下降。
四.本章小結
本文主要講解了圖像的量化處理和採樣處理,從基本機率到操做,再到擴展進行全方位講解,而且補充了基於K-Means聚類算法的量化處理和局部馬賽克特效處理,最後補充了圖像金字塔相關知識。該章節知識點可以將生活中的圖像轉換爲數字圖像,更好地爲後續的圖像處理提供幫助。但願這篇基礎性文章對讀者有必定幫助,也但願這些知識點爲讀者從事Python圖像處理相關項目實踐或科學研究提供必定基礎。
時光嘀嗒嘀嗒的流失,這是我在CSDN寫下的第八篇年終總結,比以往時候來的更早一些。《敏而多思,寧靜致遠》,僅以此篇記念這風雨兼程的一年,這感恩的一年。列車上只寫了一半,這兩天完成,思遠,思君O(∩_∩)O
2020年8月18新開的「娜璋AI安全之家」,主要圍繞Python大數據分析、網絡空間安全、人工智能、Web滲透及攻防技術進行講解,同時分享CCF、SCI、南核北核論文的算法實現。娜璋之家會更加系統,並重構做者的全部文章,從零講解Python和安全,寫了近十年文章,真心想把本身所學所感所作分享出來,還請各位多多指教,真誠邀請您的關注!謝謝。
(By:Eastmount 2020-11-10 深夜10點夜於武漢 http://blog.csdn.net/eastmount/ )
參考文獻: [1] 岡薩雷斯著. 數字圖像處理(第3版)[M]. 北京:電子工業出版社,2013. [2] yunfung. 數字圖像基礎之圖像取樣和量化(Image Sampling and Quantization)[EB/OL]. (2017-04-23). https://www.cnblogs.com/yunfung/p/6753337.html. [3] 阮秋琦. 數字圖像處理學(第3版)[M]. 北京:電子工業出版社,2008. [4] zqhwando. 圖像處理中的採樣與量化[EB/OL]. (2017-12-22). https://blog.csdn.net/zqhwando/article/details/78871140. [5] eastmount. [數字圖像處理] 三.MFC實現圖像灰度、採樣和量化功能詳解[EB/OL]. (2015-05-28). https://blog.csdn.net/eastmount/article/details/46010637. [6] 師寇. Python + opencv 實現圖片馬賽克[EB/OL]. (2017-11-08). https://blog.csdn.net/weixin_38283159/article/details/78479791. [7] 毛星雲,冷雪飛. OpenCV3編程入門[M]. 北京:電子工業出版社,2015.