OpencvPython正经教程 ■(〇)标准模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import cv2 as cvimport numpy as npimport os.path as pafrom matplotlib import pyplot as pltres = '../../AssetResources' img = np.zeros((300 , 300 ), dtype=np.uint8) img[0 :img.shape[0 ], 0 :img.shape[1 ]] = 255 cv.imshow('img' , img) cv.waitKey(0 ) cv.destroyAllWindows()
【模块引入】 之后都使用模块简写来代替模块全称
1 2 3 4 import cv2 as cv import numpy as np import os.path as pa from matplotlib import pyplot as plt
■(一)图像处理基础框架 【图像读取】 cv.imread()【读取图像】
cv.IMREAD_UNCHANGED 或 -1 (原格式)
cv.IMREAD_GRAYSCALE 或 0 (灰度)
cv.IMREAD_COLOR 或 1 (三通道)
cv.IMREAD_ANYDEPTH 或 2 (高位图)//cv.IMREAD_ANYCOLOR 或 4 (其他颜色)
cv.IMREAD_REDUSED_COLOR_2/4/8 (三通道缩小)//cv.IMREAD_REDUSED_GRAYSCALE_2/4/8 (灰度缩小)
1 2 3 res = '../../AssetResources' img = cv.imread(pa.join(res, 'Images/zt_1.png' ), cv.IMREAD_COLOR)
【窗口定义】 1 2 cv.namedWindow('win_1' )
【图像显示】 cv.imshow()【显示到窗口里】
【窗口等待】 cv.waitkey()【等待输入】
【窗口返回】 cv.destroyWindow()【返回窗口】 cv.destroyAllWindows()【全部返回】
1 2 cv.destroyWindow('win' ) cv.destroyAllWindows()
【图像写入】 cv.imwrite()【图像输出】
1 2 res = '../../AssetResources' cv.imwrite(pa.join(res, 'Images/zt_2.png' ), img)
■(二)通道与像素 【图像信息】
【图像类型】 (二值图)
(灰度图(8位))
(彩色图(8位))
【无中生有】 np.zeros()【生成一个元素都为0的数组】
np.ones()【生成一个元素都为1的数组】
np.random.randint()【生成一个元素随机的数组】
1 2 3 4 5 6 img0 = np.zeros((5 , 6 , 3 ), dtype=np.uint8) img1 = np.ones((5 , 6 , 3 ), dtype=np.uint8) img2 = np.random.randint(0 , 256 , size=[5 , 6 , 3 ], dtype=np.uint8)
【使用切刀】 [行数开始 : 行数结束, 列数开始 : 列数结束, 通道数开始 : 通道数结束]【表示图像中的一个部分】
[:, :, :]【表示整张图(三通道)】
[:, :]【表示整张图(灰度图)】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 img = cv.imread(pa.join(res, 'Images/yw.png' ), -1 ) print (type (img))list_b = img[:, :, 0 ] list_g = img[:, :, 1 ] list_r = img[:, :, 2 ] cv.imshow('showOri' , img) img[:, :, 0 ] = 255 - list_b img[:, :, 1 ] = list_g img[:, :, 2 ] = list_r cv.imshow('showChanged' , img) cv.imwrite(pa.join(res, 'Images/output.png' ), img) blue = np.zeros((300 , 300 , 3 ), dtype=np.uint8) blue[:, :, 0 ] = 255 cv.imshow('blue' , blue) green = np.zeros((300 , 300 , 3 ), dtype=np.uint8) green[:, :, 1 ] = 255 cv.imshow('green' , green) red = np.zeros((300 , 300 , 3 ), dtype=np.uint8) red[:, :, 2 ] = 255 cv.imshow('red' , red) bgrImg = np.zeros((300 , 300 , 3 ), dtype=np.uint8) bgrImg[:, 0 :100 , 0 ] = 255 bgrImg[:, 100 :200 , 1 ] = 255 bgrImg[:, 200 :300 , 2 ] = 255 bgrImg[0 :100 , :, 0 ] = 255 bgrImg[100 :200 , :, 1 ] = 255 bgrImg[200 :300 , :, 2 ] = 255 cv.imshow('bgrImg' , bgrImg) cv.waitKey(0 ) cv.destroyAllWindows()
【访问像素】 cv.item()【读取某个像素或元素】
cv.itemset()【写入某个像素或元素】
1 2 3 4 5 img = np.random.randint(10 , 200 , size=[500 , 500 , 3 ], dtype=np.uint8) print (img.item(3 , 2 , 1 )) img.itemset((3 , 2 , 1 ), 255 ) print (img.item(3 , 2 , 1 ))
【通道拆合】 cv.split()【通道拆分】
cv.merge()【通道合并】
1 2 b, g, r = cv.split(img) ret = cv.merge([255 - g, b, r * 2 ])
■(三)图像混合与位运算 【图像加法】 +
cv.add()【加法】
1 2 img2 = img1 + img1 img3 = cv.add(img1, img1)
【图像混合】 cv.addWeighted()【加权混合】
1 2 3 4 5 6 cut3 = cv.addWeighted(cut1, 0.3 , cut2, 0.7 , 50 )
【逻辑运算】
【按位运算】 cv.bitwise_and()【与】
cv.bitwise_or()【或】
cv.bitwise_xor()【异或】
cv.bitwise_not()【非】
1 2 3 4 5 6 7 8 9 10 11 img = cv.imread(pa.join(res, 'Images/dr.jpg' ), cv.IMREAD_REDUCED_COLOR_4) imgMask = np.zeros(img.shape, dtype=np.uint8) imgMask[500 :850 , 200 :400 ] = 255 masked = cv.bitwise_or(img, imgMask)
【掩模(遮罩)】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 img1 = np.ones((5 , 5 ), dtype=np.uint8) * 3 img2 = np.ones((5 , 5 ), dtype=np.uint8) * 5 mask = np.zeros((5 , 5 ), dtype=np.uint8) mask[2 :4 , 2 :4 ] = 1 img3 = cv.add(img1, img2, mask=mask) print (img3)img = cv.imread(pa.join(res, 'Images/dr.jpg' ), cv.IMREAD_REDUCED_COLOR_4) imgMask = np.zeros(img.shape, dtype=np.uint8) imgMask[400 :800 , 400 :600 ] = 255 imgMask[100 :500 , 100 :400 ] = 255 changed = cv.bitwise_and(img, img, imgMask) for i in range (3 ): changed[:, :, i] = cv.add(changed[:, :, i], 100 ) cv.imshow('img' , img) cv.imshow('imgMask' , imgMask) cv.imshow('changed' , changed) cv.waitKey(0 ) cv.destroyAllWindows()
【位平面分解】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 img = cv.imread(pa.join(res, 'Images/zt.jpg' ), cv.IMREAD_REDUCED_GRAYSCALE_2) cv.imshow('img' , img) w, h = img.shape x = np.zeros((w, h, 8 ), dtype=np.uint8) for i in range (8 ): x[:, :, i] = 2 ** i r = np.zeros((w, h, 8 ), dtype=np.uint8) for i in range (8 ): r[:, :, i] = cv.bitwise_and(img, x[:, :, i]) mask1 = r[:, :, i] > 0 mask2 = r[:, :, i] <= 0 r[mask1] = 255 r[mask2] = 0 cv.imshow(str (i), r[:, :, i]) cv.imwrite(str (i) + '_zt.png' , r[:, :, i]) cv.waitKey(0 ) cv.destroyAllWindows()
【图像加密】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 img = cv.imread(pa.join(res, 'Images/zt.jpg' ), 0 ) r, c, cha = img.shape img_b = img[:, :, 0 ] img_g = img[:, :, 1 ] img_r = img[:, :, 2 ] key = np.random.randint(0 , 256 , size=[r, c], dtype=np.uint8) img_enc_b = cv.bitwise_xor(img_b, key) img_enc_g = cv.bitwise_xor(img_g, key) img_enc_r = cv.bitwise_xor(img_r, key) img_enc = cv.merge([img_enc_b, img_enc_g, img_enc_r]) cv.imwrite(pa.join(res, 'Images/output.jpg' ), img_enc) cv.imwrite(pa.join(res, 'Images/key.jpg' ), key) img_enc_b = img_enc[:, :, 0 ] img_enc_g = img_enc[:, :, 1 ] img_enc_r = img_enc[:, :, 2 ] img_dec_b = cv.bitwise_xor(img_enc_b, key) img_dec_g = cv.bitwise_xor(img_enc_g, key) img_dec_r = cv.bitwise_xor(img_enc_r, key) img_dec = cv.merge([img_dec_b, img_dec_g, img_dec_r]) cv.imshow('img' , img) cv.imshow('key' , key) cv.imshow('encryption' , img_enc) cv.imshow('decryption' , img_dec) cv.waitKey(0 ) cv.destroyAllWindows()
【数字水印】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 img = cv.imread(pa.join(res, 'Images/zt.jpg' ), cv.IMREAD_REDUCED_GRAYSCALE_4) watermark = cv.imread(pa.join(res, 'Images/watermark.png' ), cv.IMREAD_REDUCED_GRAYSCALE_4) cv.imshow('img' , img) cv.imshow('watermark' , watermark) row_o, col_o = img.shape row_w, col_w = watermark.shape row_min, col_min = min (row_o, row_w), min (col_o, col_w) minWater = watermark[ int (row_w / 2 - row_min / 2 ):int (row_w / 2 + row_min / 2 ), int (col_w / 2 - col_min / 2 ):int (col_w / 2 + col_min / 2 ) ] resizeWater = np.zeros((row_o, col_o), dtype=np.uint8) resizeWater[ int (row_o / 2 - row_min / 2 ):int (row_o / 2 + row_min / 2 ), int (col_o / 2 - col_min / 2 ):int (col_o / 2 + col_min / 2 ) ] = minWater watermarkWhiteArea = resizeWater[:, :] > 0 resizeWater[watermarkWhiteArea] = 1 t254 = np.ones((row_o, col_o), dtype=np.uint8) * 254 img_bit7 = cv.bitwise_and(img, t254) img_rebit = cv.bitwise_or(img_bit7, resizeWater) cv.imshow('rebit' , img_rebit) t001 = np.ones((row_o, col_o), dtype=np.uint8) * 1 img_waterbit = cv.bitwise_and(img_rebit, t001) img_waterbitWhiteArea = img_waterbit[:, :] > 0 img_waterbit[img_waterbitWhiteArea] = 255 cv.imshow('waterbit' , img_waterbit) cv.waitKey(0 ) cv.destroyAllWindows()
■(四)色彩空间 【色彩空间类型】 (RGB/BGR)
(GRAY)
(XYZ)
(HSV)
【色彩空间转换】 cv.cvtColor()【色彩空间转换】
1 2 imgtest = cv.imread(pa.join(res, 'Images/dr.jpg' ), 1 ) rsttest = cv.cvtColor(imgtest, cv.COLOR_BGR2HSV)
【颜色选择】 cv.inRange()【判断是否在某范围内】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 minS, maxS = 0 , 255 minV, maxV = 0 , 255 img = cv.imread(pa.join(res, 'Images/dr.jpg' ), cv.IMREAD_REDUCED_COLOR_4) hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV) cv.imshow('img' , img) minBlue = np.array([100 , minS, minV]) maxBlue = np.array([150 , maxS, maxV]) mask = cv.inRange(hsv, minBlue, maxBlue) blue = cv.bitwise_and(img, img, mask=mask) cv.imshow('blue' , blue) minGreen = np.array([40 , minS, minV]) maxGreen = np.array([60 , maxS, maxV]) mask = cv.inRange(hsv, minGreen, maxGreen) green = cv.bitwise_and(img, img, mask=mask) cv.imshow('green' , green) minRed = np.array([0 , minS, minV]) maxRed = np.array([30 , maxS, maxV]) mask = cv.inRange(hsv, minRed, maxRed) red = cv.bitwise_and(img, img, mask=mask) cv.imshow('red' , red) cv.waitKey(0 ) cv.destroyAllWindows()
【Alpha透明通道】 1 2 3 4 5 img = cv.imread(pa.join(res, 'Images/zt_alpha.png' ), -1 ) b, g, r, a = cv.split(img) cv.imshow('img' , img) a[:, :] = 125 bgra125 = cv.merge([b, g, r, a])
■(五)几何变换 【缩放】 cv.resize()【重置大小】
cv.INTER_NEAREST (最邻近插值)
cv.INTER_LINEAR (双线性插值)
cv.INTER_CUBIC (三次样条插值)
cv.INTER_AREA (区域插值)
cv.INTER_LINEAR_EXACT (位精确双线性插值)
1 2 3 4 5 img = cv.imread(pa.join(res, 'Images/zt.jpg' ), -1 ) row, col = img.shape[:2 ] size = (int (col * 0.1 ), int (row * 0.1 )) rst = cv.resize(img, size, cv.INTER_AREA)
【翻转】 cv.flip()【翻转】
1 2 3 4 img = cv.imread(pa.join(res, 'Images/zt.jpg' ), -1 ) flipx = cv.flip(img, 0 ) flipy = cv.flip(img, 1 ) flipxy = cv.flip(img, -1 )
【仿射(映射)】 cv.warpAffine()【仿射】
(手动矩阵构成) 1 2 3 4 5 6 7 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), -1 ) height, width = img.shape[:2 ] x, y = 0 , 0 M = np.float32([[1 , -0.5 , x], [0 , 1 , y]]) move = cv.warpAffine(img, M, (width, height))
(旋转矩阵构成) cv.getRotationMatrix2D()【带有旋转量的矩阵构成】
1 2 3 4 5 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), -1 ) height, width = img.shape[:2 ] M = cv.getRotationMatrix2D((width / 2 , height / 2 ), 45 , 0.6 ) move = cv.warpAffine(img, M, (width, height))
(平行四边形构成) cv.getAffineTransform()【带有坐标量的矩阵构成】
1 2 3 4 5 6 7 8 9 10 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), -1 ) height, width = img.shape[:2 ] p1 = np.float32([[0 , 0 ], [height, 0 ], [0 , width]]) p2 = np.float32([[0 , height * 0.1 ], [width * 0.8 , height * 0.25 ], [width * 0.1 , height * 0.5 ]]) M = cv.getAffineTransform(p1, p2) move = cv.warpAffine(img, M, (width, height))
【四角变幻】 cv.warpPerspective()【透视变幻】
cv.getPerspectiveTransform()【透视矩阵构成】
1 2 3 4 5 6 7 8 9 10 11 12 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), -1 ) height, width = img.shape[:2 ] p1 = np.float32([[0 , 0 ], [width, 0 ], [0 , height], [width, height]]) p2 = np.float32([[width / 5 , 0 ], [width / 5 * 4 , 100 ], [0 , height], [width, height]]) M = cv.getPerspectiveTransform(p1, p2) move = cv.warpPerspective(img, M, (width, height))
【逐像素映射】 remap()【逐像素映射】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 img = np.random.randint(0 , 256 , size=[4 , 5 ], dtype=np.uint8) row, col = img.shape mapx = np.zeros(img.shape, np.float32) mapy = np.zeros(img.shape, np.float32) for i in range (row): for j in range (col): mapx.itemset((i, j), j) mapy.itemset((i, j), i) rst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)
■(六)阈值 【阈值提取处理】 cv.threshold()【阈值提取】
cv.THRESH_BINARY (二值化处理)
cv.THRESH_BINARY_INV (反二值化处理)
cv.THRESH_TRUNC (截断处理)
cv.THRESH_TOZERO (低阈值零处理)
cv.YHRESH_TOZERO_INV (超阈值零处理)
1 2 3 4 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), 0 ) thresRet, rst = cv.threshold(img, 127 , 255 , cv.THRESH_TOZERO_INV) thres0 = rst[:, :] == 0 rst[thres0] = 255
【自适应阈值处理】 cv.adaptiveThreshold()【自适应阈值处理】
cv.ADAPTIVE_THRESH_MEAN_C (权重一致自适应法)
cv.ADAPTIVE_THRESH_GAUSSIAN_C (高斯方程自适应法)
1 2 3 4 5 6 img = cv.imread(pa.join(res, 'Images/dr.jpg' ), cv.IMREAD_REDUCED_GRAYSCALE_4) thresRet, rst = cv.threshold(img, 127 , 255 , cv.THRESH_TOZERO) rst2 = cv.adaptiveThreshold( img, 255 , cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 5 , 1 ) rst3 = cv.adaptiveThreshold( img, 255 , cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 5 , 5 )
【自动匹配阈值处理】 cv.THRESH_OTSU (自动匹配阈值处理)
1 2 3 img = cv.imread(pa.join(res, 'Images/zt.jpg' ), cv.IMREAD_REDUCED_GRAYSCALE_4) thresRet1, rst1 = cv.threshold(img, 127 , 255 , cv.THRESH_BINARY) thresRet2, rst2 = cv.threshold(img, 127 , 255 , cv.THRESH_OTSU)
■(七)图像滤波(模糊)
【均值滤波】 1 2 3 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), -1 ) blur = cv.blur(img, (10 , 10 ))
【方框滤波】 1 2 3 4 5 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), -1 ) blur = cv.boxFilter(img, -1 , (10 , 10 )) blur1 = cv.boxFilter(img, -1 , (10 , 10 ), normalize=1 ) blur2 = cv.boxFilter(img, -1 , (10 , 10 ), normalize=0 )
【高斯滤波】 1 2 3 img = cv.imread(pa.join(res, 'Images/lena.jpg' )) blur = cv.GaussianBlur(img, (11 , 11 ), 6 , 4 )
【中值滤波】 1 2 3 img = cv.imread(pa.join(res, 'Images/lena.jpg' )) blur = cv.medianBlur(img, 9 )
【双边滤波】 1 2 3 img = cv.imread(pa.join(res, 'Images/lena.jpg' )) blur = cv.bilateralFilter(img, 5 , 50 , 50 )
【自制2D卷积】 1 2 3 4 img = cv.imread(pa.join(res, 'Images/lena.jpg' )) kernel = np.ones((9 , 9 ), np.float32) / (9 * 9 ) blur = cv.filter2D(img, -1 , kernel)
■(八)形态学
【腐蚀】 cv.erode()【腐蚀形态学】
1 2 3 4 5 6 7 8 9 10 11 12 13 img = np.zeros((5 , 5 ), dtype=np.uint8) img[1 :4 , 1 :4 ] = 1 kernel = np.ones((3 , 1 ), dtype=np.uint8) ero = cv.erode(img, kernel) print ('img\n' , img)print ('kernel\n' , kernel)print ('ero\n' , ero)img = cv.imread(pa.join(res, 'Images/morph.png' ), -1 ) kernel = np.ones((5 , 5 ), dtype=np.uint8) ero = cv.erode(img, kernel) cv.imshow('img' , img) cv.imshow('ero' , ero)
【膨胀】 cv.dilate()【膨胀形态学】
1 2 3 4 5 6 7 8 9 10 11 12 13 img = np.zeros((5 , 5 ), dtype=np.uint8) img[2 :3 , 1 :4 ] = 1 kernel = np.ones((3 , 1 ), dtype=np.uint8) dil = cv.dilate(img, kernel) print ('img\n' , img)print ('kernel\n' , kernel)print ('dil\n' , dil)img = cv.imread(pa.join(res, 'Images/morph.png' ), -1 ) kernel = np.ones((5 , 5 ), dtype=np.uint8) dil = cv.dilate(img, kernel) cv.imshow('img' , img) cv.imshow('dil' , dil)
【通用函数】 cv.morphologyEx()【形态学修改】
cv.MORPH_ERODE (腐蚀)
cv.MORPH_DILATE (膨胀)
cv.MORPH_OPEN (开运算)
cv.MORPH_CLOSE (闭运算)
cv.MORPH_GRADIENT (形态学梯度运算)
cv.MORPH_TOPHAT (礼帽运算)
cv.MORPH_BLACKHAT (黑帽运算)
【开运算】 1 2 3 4 img = cv.imread(pa.join(res, 'Images/morph.png' ), -1 ) kernel = np.ones((5 , 5 ), dtype=np.uint8) openArg = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)
【闭运算】 1 2 3 4 img = cv.imread(pa.join(res, 'Images/morph.png' ), -1 ) kernel = np.ones((5 , 5 ), dtype=np.uint8) closeArg = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)
【形态学梯度运算】 1 2 3 4 img = cv.imread(pa.join(res, 'Images/morph.png' ), -1 ) kernel = np.ones((2 , 2 ), dtype=np.uint8) gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)
【礼帽运算】 1 2 3 4 img = cv.imread(pa.join(res, 'Images/morph.png' ), -1 ) kernel = np.ones((2 , 2 ), dtype=np.uint8) tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)
【黑帽运算】 1 2 3 4 img = cv.imread(pa.join(res, 'Images/morph.png' ), -1 ) kernel = np.ones((2 , 2 ), dtype=np.uint8) blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)
【核函数类型】 cv.getStructuringElement()【形态学核函数构造】
cv.MORPH_RECT (矩形)
cv.MORPH_CROSS (十字架)
cv.MORPH_ELLIPSE (椭圆)
1 2 3 4 5 6 7 img = cv.imread(pa.join(res, 'Images/morph.png' ), -1 ) k1 = cv.getStructuringElement(cv.MORPH_RECT, (50 , 50 )) k2 = cv.getStructuringElement(cv.MORPH_CROSS, (50 , 50 )) k3 = cv.getStructuringElement(cv.MORPH_ELLIPSE, (50 , 50 )) morph1 = cv.morphologyEx(img, cv.MORPH_DILATE, k1) morph2 = cv.morphologyEx(img, cv.MORPH_DILATE, k2) morph3 = cv.morphologyEx(img, cv.MORPH_DILATE, k3)
■(九)边缘梯度
【Sobel算子】 cv.Sobel()【sobel算子】
1 2 3 4 5 6 img = cv.imread(pa.join(res, 'Images/gradient.png' ), 0 ) sobel1 = cv.Sobel(img, cv.CV_64F, 0 , 1 ) sobel1 = cv.convertScaleAbs(sobel1) sobel2 = cv.Sobel(img, cv.CV_64F, 1 , 0 ) sobel2 = cv.convertScaleAbs(sobel2) sobel3 = cv.addWeighted(sobel1, 1 , sobel2, 1 , 0 )
【Scharr算子】 cv.Scharr()【scharr算子】
1 2 3 4 5 6 img = cv.imread(pa.join(res, 'Images/gradient.png' ), 0 ) scharr1 = cv.Scharr(img, cv.CV_64F, 0 , 1 ) scharr1 = cv.convertScaleAbs(scharr1) scharr2 = cv.Scharr(img, cv.CV_64F, 1 , 0 ) scharr2 = cv.convertScaleAbs(scharr2) scharr3 = cv.addWeighted(scharr1, 1 , scharr2, 1 , 0 )
【Laplacian算子】 cv.Laplacian()【laplacian算子】
1 2 3 img = cv.imread(pa.join(res, 'Images/gradient.png' ), 0 ) lap = cv.Laplacian(img, cv.CV_64F, ksize=1 ) lap = cv.convertScaleAbs(lap)
■(十)边缘检测 【专业边缘检测】 cv.Canny()【canny边缘检测】
1 2 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), 0 ) res = cv.Canny(img, 127 , 255 )
■(十一)图像金字塔 【高斯金字塔】
【拉普拉斯金字塔】
【图像向下采样】 1 2 3 4 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), 1 ) res1 = cv.pyrDown(img) res2 = cv.pyrDown(res1) res3 = cv.pyrDown(res2)
【图像向上采样】 1 2 3 4 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), 1 ) res1 = cv.pyrUp(img) res2 = cv.pyrUp(res1) res3 = cv.pyrUp(res2)
【拉普拉斯与恢复原图】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 img = cv.imread(pa.join(res, 'Images/lena.jpg' ), 1 ) g0 = img g1 = cv.pyrDown(g0) g2 = cv.pyrDown(g1) g3 = cv.pyrDown(g2) l0 = g0 - cv.pyrUp(g1) l1 = g1 - cv.pyrUp(g2) l2 = g2 - cv.pyrUp(g3) img = cv.imread(pa.join(res, 'Images/lena.jpg' ), 1 ) g = cv.pyrDown(cv.pyrDown(img)) u = cv.pyrUp(cv.pyrUp(g)) l = img - u reimg = u + l
■(十二)图像轮廓
【绘制轮廓】 cv.findContours()【查找图像轮廓】
cv.drawContours【绘制图像轮廓】
cv.RETR_EXTERNAL (只检测外轮廓)
cv.RETR_LIST (检测所有轮廓,不建立等级关系)
cv.RETR_CCOMP (检测所有轮廓,建立二级关系)
cv.RETR_TREE (检测所有轮廓,建立多级关系)
cv.CHAIN_APPROX_NONE (存储所有轮廓点)
cv.CHAIN_APPROX_SIMPLE (压缩所有轮廓点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 img = cv.imread(pa.join(res, 'Images/lena.jpg' )) cv.imshow('img' , img) imgg = cv.GaussianBlur(img, (11 , 11 ), 6 , 4 ) gray = cv.cvtColor(imgg, cv.COLOR_BGR2GRAY) ret, bina = cv.threshold(gray, 127 , 255 , cv.THRESH_BINARY) cv.imshow('bina' , bina) cont, hier = cv.findContours(bina, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) black = np.zeros(img.shape, dtype=np.uint8) imgContDraw1 = cv.drawContours(black, cont, 14 , (255 , 255 , 255 ), -1 ) imgContDraw2 = cv.drawContours(imgg, cont, -1 , (255 , 255 , 0 ), 1 ) cv.imshow('imgContDraw1' , imgContDraw1) cv.imshow('imgContDraw2' , imgContDraw2) cut = cv.bitwise_and(img, imgContDraw1) cv.imshow('cut' , cut)
【矩特征】 (moments矩集) cv.moments()【轮廓的矩】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 img = cv.imread(pa.join(res, 'Images/Contours/contours.png' ), cv.IMREAD_REDUCED_COLOR_2) cv.imshow('img' , img) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) ret, bina = cv.threshold(gray, 254 , 255 , cv.THRESH_BINARY) cv.imshow('bina' , bina) cont, hier = cv.findContours(bina, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) n = len (cont) contImg = [] for i in range (n): temp = np.zeros(gray.shape, dtype=np.uint8) contImg.append(temp) contImg[i] = cv.drawContours(contImg[i], cont, i, 255 , 1 ) cv.imshow(f'cont{i} ' , contImg[i]) for i in range (n): print (f'矩{i} \n' , cv.moments(cont[i])) for i in range (n): print (f'面积{i} \n' , cv.moments(cont[i])['m00' ])
(轮廓面积) cv.contourArea()【轮廓面积】
1 2 3 4 5 6 7 8 9 10 11 ... cont, hier = cv.findContours(bina, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) n = len (cont) contImg = [] for i in range (n): print (f'cont面积{i} =' , cv.contourArea(cont[i])) temp = np.zeros(gray.shape, dtype=np.uint8) contImg.append(temp) if cv.contourArea(cont[i]) > 3000 : contImg[i] = cv.drawContours(contImg[i], cont, i, 255 , 1 ) cv.imshow(f'cont{i} ' , contImg[i])
(轮廓周长) cv.arcLength()【轮廓周长】
1 2 3 4 5 6 7 8 9 10 ... cont, hier = cv.findContours(bina, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) n = len (cont) contImg = [] for i in range (n): print (f'cont长度{i} =' , cv.arcLength(cont[i], True )) temp = np.zeros(gray.shape, dtype=np.uint8) contImg.append(temp) contImg[i] = cv.drawContours(contImg[i], cont, i, 255 , 1 ) cv.imshow(f'cont{i} ' , contImg[i])
(Hu归一化中心矩) cv.HuMoments()【Hu矩】
1 2 3 4 5 6 7 8 img = cv.imread(pa.join(res, 'Images/Contours/contours.png' ), cv.IMREAD_REDUCED_COLOR_2) cv.imshow('img' , img) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) print (cv.HuMoments(cv.moments(gray)))
(轮廓匹配) cv.matchShapes()【轮廓匹配】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 img1 = cv.imread(pa.join(res, 'Images/Contours/cont1.png' ), cv.IMREAD_REDUCED_COLOR_2) img2 = cv.imread(pa.join(res, 'Images/Contours/cont2.png' ), cv.IMREAD_REDUCED_COLOR_2) img3 = cv.imread(pa.join(res, 'Images/Contours/cont3.png' ), cv.IMREAD_REDUCED_COLOR_2) gray1 = cv.cvtColor(img1, cv.COLOR_BGR2GRAY) gray2 = cv.cvtColor(img2, cv.COLOR_BGR2GRAY) gray3 = cv.cvtColor(img3, cv.COLOR_BGR2GRAY) ret1, bin1 = cv.threshold(gray1, 127 , 255 , cv.THRESH_BINARY) ret2, bin2 = cv.threshold(gray2, 127 , 255 , cv.THRESH_BINARY) ret3, bin3 = cv.threshold(gray3, 127 , 255 , cv.THRESH_BINARY) cont1, hier1 = cv.findContours(bin1, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) cont2, hier2 = cv.findContours(bin2, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) cont3, hier3 = cv.findContours(bin3, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) ret0 = cv.matchShapes(cont1[0 ], cont1[0 ], 1 , 0 ) ret1 = cv.matchShapes(cont1[0 ], cont2[0 ], 1 , 0 ) ret2 = cv.matchShapes(cont1[0 ], cont3[0 ], 1 , 0 ) print (ret0)print (ret1)print (ret2)
【形状匹配】 (正矩形包围框) cv.boundingRect()【正矩形包围框】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 img = cv.imread(pa.join(res, 'Images/Contours/cont1.png' )) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) ret, bina = cv.threshold(gray, 127 , 255 , cv.THRESH_BINARY) cont, hier = cv.findContours(bina, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) x, y, w, h = cv.boundingRect(cont[0 ]) print (x, y, w, h)arr = np.array([[x, y], [x + w, y], [x + w, y + h], [x, y + h]]) cv.drawContours(img, [arr], -1 , (0 , 0 , 255 ), 10 ) cv.rectangle(img, (x, y), (x + w, y + h), (255 , 255 , 0 ), 2 ) cv.imshow('img' , img) rect = cv.boundingRect(cont[0 ]) print (rect)
(最小矩形包围框) cv.minAreaRect()【最小矩形包围框】
cv.boxPoints()【点集构成】
1 2 3 4 5 6 7 8 9 img = cv.imread(pa.join(res, 'Images/Contours/cont1.png' )) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) ret, bina = cv.threshold(gray, 127 , 255 , cv.THRESH_BINARY) cont, hier = cv.findContours(bina, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) rect = cv.minAreaRect(cont[0 ]) points = cv.boxPoints(rect) points = np.int0(points) img1 = cv.drawContours(img, [points], -1 , (0 , 0 , 255 ), 10 ) cv.imshow('img1' , img1)
(最小圆包围框) cv.minEnclosingCircle()【最小圆包围框】
1 2 3 4 5 6 7 img = cv.imread(pa.join(res, 'Images/Contours/cont1.png' )) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) ret, bina = cv.threshold(gray, 127 , 255 , cv.THRESH_BINARY) cont, hier = cv.findContours(bina, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) (x, y), radius = cv.minEnclosingCircle(cont[0 ]) cv.circle(img, (int (x), int (y)), int (radius), (255 , 255 , 0 ), 2 ) cv.imshow('img' , img)
(最优椭圆包围框) cv.fitEllipse()【最优椭圆包围框】
1 2 3 4 5 6 7 img = cv.imread(pa.join(res, 'Images/Contours/cont3.png' )) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) ret, bina = cv.threshold(gray, 127 , 255 , cv.THRESH_BINARY) cont, hier = cv.findContours(bina, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) ellipse = cv.fitEllipse(cont[0 ]) cv.ellipse(img, ellipse, (255 , 255 , 0 ), 2 ) cv.imshow('img' , img)
(最优直线导向) cv.fitLine()【最优直线导向】
1 2 3 4 5 6 7 8 9 10 img = cv.imread(pa.join(res, 'Images/Contours/cont3.png' )) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) ret, bina = cv.threshold(gray, 127 , 255 , cv.THRESH_BINARY) cont, hier = cv.findContours(bina, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) row, col = img.shape[:2 ] [vx, vy, x, y] = cv.fitLine(cont[0 ], cv.DIST_L2, 0 , 0.01 , 0.01 ) lefty = int ((-x * vy / vx) + y) righty = int (((col - x) * vy / vx) + y) cv.line(img, (col - 1 , righty), (0 , lefty), (255 , 255 , 0 ), 2 ) cv.imshow('img' , img)
(最小三角形包围框) cv.minEnclosingTriangle()【最小三角形包围框】
1 2 3 4 5 6 7 8 img = cv.imread(pa.join(res, 'Images/Contours/cont3.png' )) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) ret, bina = cv.threshold(gray, 127 , 255 , cv.THRESH_BINARY) cont, hier = cv.findContours(bina, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) area, tran = cv.minEnclosingTriangle(cont[0 ]) for i in range (0 , 3 ): cv.line(img, tuple (tran[i][0 ]), tuple (tran[(i + 1 ) % 3 ][0 ]), (255 , 255 , 0 ), 2 ) cv.imshow('img' , img)
(相似多边形) cv.approxPolyDP()【相似多边形】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 img = cv.imread(pa.join(res, 'Images/Contours/cont3.png' )) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) ret, bina = cv.threshold(gray, 127 , 255 , cv.THRESH_BINARY) cont, hier = cv.findContours(bina, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) adp = img.copy() epsilon = 0.1 * cv.arcLength(cont[0 ], True ) approx = cv.approxPolyDP(cont[0 ], epsilon, True ) adp = cv.drawContours(adp, [approx], -1 , (0 , 0 , 255 ), 2 ) cv.imshow('0.1' , adp) adp = img.copy() epsilon = 0.02 * cv.arcLength(cont[0 ], True ) approx = cv.approxPolyDP(cont[0 ], epsilon, True ) adp = cv.drawContours(adp, [approx], -1 , (0 , 0 , 255 ), 2 ) cv.imshow('0.05' , adp) adp = img.copy() epsilon = 0.005 * cv.arcLength(cont[0 ], True ) approx = cv.approxPolyDP(cont[0 ], epsilon, True ) adp = cv.drawContours(adp, [approx], -1 , (0 , 0 , 255 ), 2 ) cv.imshow('0.01' , adp)
【凸包】 (凸包) cv.convexHull()【获得凸包】
1 2 hull = cv.convexHull(cont[0 ]) cv.polylines(img, [hull], True , (0 , 255 , 0 ), 2 )
(凸缺陷) cv.convexityDefects()【获得凸缺陷】
1 2 3 4 5 6 7 8 9 hull = cv.convexHull(cont[0 ], returnPoints=False ) defects = cv.convexityDefects(cont[0 ], hull) for i in range (defects.shape[0 ]): s, e, f, d = defects[i, 0 ] start = tuple (cont[0 ][s][0 ]) end = tuple (cont[0 ][e][0 ]) far = tuple (cont[0 ][f][0 ]) cv.line(img, start, end, [0 , 0 , 255 ], 2 ) cv.circle(img, far, 5 , [255 , 0 , 0 ], -1 )
(是否凸) cv.isContourConvex()【判断形状是否凸】
1 2 3 4 5 6 7 8 9 10 11 12 img1 = img.copy() hull = cv.convexHull(cont[0 ]) cv.polylines(img1, [hull], True , (0 , 255 , 0 ), 2 ) cv.imshow('img1' , img1) print ('img1\n' , cv.isContourConvex(hull))img2 = img.copy() epsilon = 0.01 * cv.arcLength(cont[0 ], True ) approx = cv.approxPolyDP(cont[0 ], epsilon, True ) img2 = cv.drawContours(img2, [approx], 0 , (0 , 0 , 255 ), 2 ) cv.imshow('img2' , img2) print ('img2\n' , cv.isContourConvex(approx))
(点与轮廓) cv.pointPolygonTest()【点到轮廓的距离和点是否在轮廓内】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 hull = cv.convexHull(cont[0 ]) cv.polylines(img, [hull], True , (0 , 255 , 0 ), 2 ) dista = cv.pointPolygonTest(hull, (300 , 150 ), True ) distaf = cv.pointPolygonTest(hull, (300 , 150 ), False ) cv.putText(img, 'A' , (300 , 150 ), cv.FONT_HERSHEY_SIMPLEX, 1 , (0 , 255 , 0 ), 2 ) print ('distA' , dista)print ('distAf' , distaf)distb = cv.pointPolygonTest(hull, (423 , 112 ), True ) distbf = cv.pointPolygonTest(hull, (423 , 112 ), False ) cv.putText(img, 'B' , (423 , 112 ), cv.FONT_HERSHEY_SIMPLEX, 1 , (0 , 255 , 0 ), 2 ) print ('distB' , distb)print ('distBf' , distbf)
【形状场景距离】 cv.createShapeContextDistanceExtractor()【标准形状场景距离算子构造】
cv.createHausdorffDistanceExtractor()【Hausdorff场景距离算子构造】
cv.createShapeContextDistanceExtractor().computeDistance()【标准计算两个形状的距离】
cv.createHausdorffDistanceExtractor().computeDistance()【Hausdorff计算两个形状的距离】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 img1 = cv.imread(pa.join(res, 'Images/Contours/cont1.png' )) gray1 = cv.cvtColor(img1, cv.COLOR_BGR2GRAY) ret1, bina1 = cv.threshold(gray1, 127 , 255 , cv.THRESH_BINARY) cont1, hier1 = cv.findContours(bina1, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) img2 = cv.imread(pa.join(res, 'Images/Contours/cont2.png' )) gray2 = cv.cvtColor(img2, cv.COLOR_BGR2GRAY) ret2, bina2 = cv.threshold(gray2, 127 , 255 , cv.THRESH_BINARY) cont2, hier2 = cv.findContours(bina2, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) img3 = cv.imread(pa.join(res, 'Images/Contours/cont3.png' )) gray3 = cv.cvtColor(img3, cv.COLOR_BGR2GRAY) ret3, bina3 = cv.threshold(gray3, 127 , 255 , cv.THRESH_BINARY) cont3, hier3 = cv.findContours(bina3, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) sd = cv.createShapeContextDistanceExtractor() d1 = sd.computeDistance(cont1[0 ], cont1[0 ]) d2 = sd.computeDistance(cont1[0 ], cont2[0 ]) d3 = sd.computeDistance(cont1[0 ], cont3[0 ]) img1 = cv.imread(pa.join(res, 'Images/Contours/cont1.png' )) img2 = cv.imread(pa.join(res, 'Images/Contours/cont2.png' )) img3 = cv.imread(pa.join(res, 'Images/Contours/cont3.png' )) gray1 = cv.cvtColor(img1, cv.COLOR_BGR2GRAY) gray2 = cv.cvtColor(img2, cv.COLOR_BGR2GRAY) gray3 = cv.cvtColor(img3, cv.COLOR_BGR2GRAY) ret1, bina1 = cv.threshold(gray1, 127 , 255 , cv.THRESH_BINARY) ret2, bina2 = cv.threshold(gray2, 127 , 255 , cv.THRESH_BINARY) ret3, bina3 = cv.threshold(gray3, 127 , 255 , cv.THRESH_BINARY) cont1, hier1 = cv.findContours(bina1, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) cont2, hier2 = cv.findContours(bina2, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) cont3, hier3 = cv.findContours(bina3, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) hd = cv.createHausdorffDistanceExtractor() d1 = hd.computeDistance(cont1[0 ], cont1[0 ]) d2 = hd.computeDistance(cont1[0 ], cont2[0 ]) d3 = hd.computeDistance(cont1[0 ], cont3[0 ])
【轮廓特殊值】 np.nonzero()【找出数组中非零元素的位置】
np.transpose()【将两个数组移项】
cv.findNonZero()【找出数组中非零元素的索引】
cv.minMaxLoc()【最大值最小值及其位置】
cv.mean()【平均颜色平均灰度】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 x, y, w, h = cv.boundingRect(cont[0 ]) aspectRatio = float (w) / h extend = cv.contourArea(cont[0 ]) / (w * h) solidity = cv.contourArea(cont[0 ]) / cv.contourArea(cv.convexHull(cont[0 ])) equivalent = np.sqrt((4 * cv.contourArea(cont[0 ])) / np.pi) (ellipsex, ellipsey), (horiLen, vertLen), angle = cv.fitEllipse(cont[0 ]) mask1 = np.zeros(gray, dtype=np.uint8) trans1 = np.transpose(np.nonzero(mask1)) trans2 = cv.findNonZero(mask1) minVal, maxVal, minLoc, maxLoc = cv.minMaxLoc(gray, mask=mask1) meanVal = cv.mean(img, mask=mask1) leftmost = tuple (cont[0 ][cont[0 ][:, :, 0 ].argmin()][0 ]) rightmost = tuple (cont[0 ][cont[0 ][:, :, 0 ].argmax()][0 ]) topmost = tuple (cont[0 ][cont[0 ][:, :, 1 ].argmin()][0 ]) bottommost = tuple (cont[0 ][cont[0 ][:, :, 1 ].argmax()][0 ])
■(十三)直方图
【绘制直方图】 matplotlib.pyplot.hist()【mat模块直方图绘制】
cv.calcHist【获得直方图信息】
matplotlib.pyplot.plot()【mat模块绘制直方图信息】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import matplotlib.pyplot as pltimg = cv.imread(pa.join(res, 'Images/lena.jpg' )) plt.hist(img.ravel(), 256 , color='y' ) histb = cv.calcHist([img], [0 ], None , [256 ], [0 , 255 ]) histg = cv.calcHist([img], [1 ], None , [256 ], [0 , 255 ]) histr = cv.calcHist([img], [2 ], None , [256 ], [0 , 255 ]) plt.plot(histb, color='b' ) plt.plot(histg, color='g' ) plt.plot(histr, color='r' ) plt.plot(histb + histg + histr) plt.show()
【直方图加遮罩】 1 2 3 4 5 6 7 8 9 10 11 12 import matplotlib.pyplot as pltimg = cv.imread(pa.join(res, 'Images/lena.jpg' )) mask = np.zeros(img.shape[:2 ], dtype=np.uint8) mask[int (mask.shape[0 ]/2 - 100 ):int (mask.shape[0 ]/2 + 100 ), int (mask.shape[1 ]/2 - 100 ):int (mask.shape[1 ]/2 + 100 )] = 255 histb = cv.calcHist([img], [0 ], None , [256 ], [0 , 255 ]) histbm = cv.calcHist([img], [0 ], mask, [256 ], [0 , 255 ]) plt.plot(histb, color='b' ) plt.plot(histbm, color='g' ) plt.show()
【图像均衡化】 cv.equalizeHist()【图像均衡化】
1 2 3 4 5 6 7 8 9 10 import matplotlib.pyplot as pltimg = cv.imread(pa.join(res, 'Images/dr.jpg' ), cv.IMREAD_REDUCED_GRAYSCALE_4) equ = cv.equalizeHist(img) plt.figure('img' ) plt.hist(img.ravel(), 256 ) plt.figure('equ' ) plt.hist(equ.ravel(), 256 ) plt.show()
【matplotlib的绘图介绍】 matplotlib.pyplot.figure()【开启一个pyplot窗口】
matplotlib.pyplot.subplot()【在pyplot窗口里添加子对象】
matplotlib.pyplot.show()【显示pyplot窗口】
1 2 3 4 5 6 7 8 9 10 11 import matplotlib.pyplot as pltimg = cv.imread(pa.join(res, 'Images/dr.jpg' ), cv.IMREAD_REDUCED_GRAYSCALE_4) equ = cv.equalizeHist(img) plt.figure('img' ) plt.subplot(1 , 4 , 1 ), plt.hist(img.ravel(), 256 ) plt.subplot(1 , 4 , 2 ), plt.hist(equ.ravel(), 256 ) plt.subplot(1 , 4 , 3 ), plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB)) plt.subplot(1 , 4 , 4 ), plt.imshow(cv.cvtColor(equ, cv.COLOR_BGR2RGB)) plt.show()
■(十四)傅里叶变换
【FFT傅里叶变换】 numpy.fft.fft2()【傅里叶变换】
numpy.fft.fftshift()【矫正傅里叶变换】
numpy.fft.ifft2()【逆傅里叶变换】
numpy.fft.ifftshift()【逆矫正傅里叶变换】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import matplotlib.pyplot as pltimg = cv.imread(pa.join(res, 'Images/dr.jpg' ), 0 ) f = np.fft.fft2(img) fshift = np.fft.fftshift(f) ishift = np.fft.ifftshift(fshift) iimg = np.fft.ifft2(ishift) plt.subplot(131 ), plt.imshow(img, cmap='gray' ), plt.title('original' ), plt.axis('off' ) spectrum = 20 * np.log(np.abs (fshift)) plt.subplot(132 ), plt.imshow(spectrum, cmap='gray' ), plt.title('result' ), plt.axis('off' ) iimg = np.abs (iimg) plt.subplot(133 ), plt.imshow(iimg, cmap='gray' ), plt.title('iimg' ), plt.axis('off' ) plt.show()
【二维高通低通处理】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import matplotlib.pyplot as pltimg = cv.imread(pa.join(res, 'Images/dr.jpg' ), 0 ) f = np.fft.fft2(img) fshift = np.fft.fftshift(f) r, c = img.shape rh, ch = int (r/2 ), int (c/2 ) deg = 2 xoff, yoff = 0 , 0 mask1 = np.ones(img.shape, dtype=np.uint8) mask1[int (rh - rh/deg + yoff):int (rh + rh/deg + yoff), int (ch - ch/deg + xoff):int (ch + ch/deg + xoff)] = 0 mask2 = np.zeros(img.shape, dtype=np.uint8) mask2[int (rh - rh/deg + yoff):int (rh + rh/deg + yoff), int (ch - ch/deg + xoff):int (ch + ch/deg + xoff)] = 1 ishift = np.fft.ifftshift(fshift) iimg = np.fft.ifft2(ishift) plt.subplot(131 ), plt.imshow(img, cmap='gray' ), plt.title('original' ), plt.axis('off' ) spectrum = 20 * np.log(np.abs (fshift) + 10 **-5 ) plt.subplot(132 ), plt.imshow(spectrum, cmap='gray' ), plt.title('result' ), plt.axis('off' ) iimg = np.abs (iimg) plt.subplot(133 ), plt.imshow(iimg, cmap='gray' ), plt.title('iimg' ), plt.axis('off' ) plt.show()
■(十五)模板匹配
【单模板单匹配结构】 cv.matchTemplate()【模板匹配】
1 2 3 4 5 6 7 8 9 10 11 12 13 img = cv.imread(pa.join(res, 'Images/dr.jpg' ), 1 ) temp = cv.imread(pa.join(res, 'Images/Template/dr_t1.png' ), 1 ) img = cv.cvtColor(img, cv.COLOR_BGR2RGB) temp = cv.cvtColor(temp, cv.COLOR_BGR2RGB) rv = cv.matchTemplate(img, temp, cv.TM_SQDIFF) minVal, maxVal, minLoc, maxLoc = cv.minMaxLoc(rv) print ('minVal\n' , minVal)print ('maxVal\n' , maxVal)th, tw = temp.shape[:2 ] topLeft = minLoc bottomRight = (topLeft[0 ] + tw, topLeft[1 ] + th) cv.rectangle(img, topLeft, bottomRight, 255 , 2 )
【单模板多匹配结构】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 img = cv.imread(pa.join(res, 'Images/Template/dr_t3.png' ), 1 ) temp = cv.imread(pa.join(res, 'Images/Template/dr_t1.png' ), 1 ) temp = cv.GaussianBlur(temp, (1 , 1 ), 6 , 4 ) img = cv.cvtColor(img, cv.COLOR_BGR2RGB) temp = cv.cvtColor(temp, cv.COLOR_BGR2RGB) res = cv.matchTemplate(img, temp, cv.TM_CCOEFF_NORMED) h, w = temp.shape[:2 ] threshold = 0.9 loc = np.where(res >= threshold) for pos in zip (*loc[::-1 ]): cv.rectangle(img, pos, (pos[0 ] + w, pos[1 ] + h), 255 , 1 )
■(十六)霍夫变换
【霍夫变换】 cv.HoughLines()【霍夫直线】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 img = cv.imread(pa.join(res, 'Images/fractal.png' ), 1 ) img = cv.cvtColor(img, cv.COLOR_BGR2RGB) gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY) edge = cv.Canny(gray, 200 , 255 , apertureSize=3 ) houghs = cv.HoughLines(edge, 1 , np.pi/180 , 300 ) blank = np.zeros(img.shape, dtype=np.uint8) try : for h in houghs: r, t = h[0 ] cost, sint = np.cos(t), np.sin(t) x0, y0 = cost * r, sint * r x1, y1 = int (x0 + 10 ** 4 * (-sint)), int (y0 + 10 ** 4 * cost) x2, y2 = int (x0 - 10 ** 4 * (-sint)), int (y0 - 10 ** 4 * cost) cv.line(blank, (x1, y1), (x2, y2), (0 , 255 , 0 ), 1 ) except TypeError: print ('no Number' ) plt.subplot(121 ), plt.imshow(edge, cmap='gray' ), plt.axis('off' ) plt.subplot(122 ), plt.imshow(blank, cmap='gray' ), plt.axis('off' ) plt.show()
【概率霍夫变换】 cv.HoughLinesP()【概率霍夫直线】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 img = cv.imread(pa.join(res, 'Images/fractal.png' ), 1 ) img = cv.cvtColor(img, cv.COLOR_BGR2RGB) gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY) edge = cv.Canny(gray, 50 , 150 , apertureSize=3 ) houghs = cv.HoughLinesP(edge, 1 , np.pi/180 , 1 , minLineLength=img.shape[0 ]/10 , maxLineGap=20 ) blank = np.zeros(img.shape, dtype=np.uint8) try : for h in houghs: x1, y1, x2, y2 = h[0 ] cv.line(blank, (x1, y1), (x2, y2), (255 , 255 , 0 ), 1 ) except TypeError: print ('no Number' ) plt.subplot(131 ), plt.imshow(img, cmap='gray' ), plt.axis('off' ) plt.subplot(132 ), plt.imshow(edge, cmap='gray' ), plt.axis('off' ) plt.subplot(133 ), plt.imshow(blank, cmap='gray' ), plt.axis('off' ) plt.show()
【霍夫圆环变换】 cv.HoughCircles()【霍夫圆环】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 img = cv.imread(pa.join(res, 'Images/dr.jpg' ), 1 ) img = cv.cvtColor(img, cv.COLOR_BGR2RGB) gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY) gray = cv.medianBlur(gray, 5 ) ruler = max (img.shape[0 ], img.shape[1 ]) / 50 print (ruler)houghs = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, 1 , int (ruler), param1=127 , param2=30 , minRadius=int (ruler * 1 ), maxRadius=int (ruler * 3 )) try : for i in houghs[0 , :]: cv.circle(img, (int (i[0 ]), int (i[1 ])), int (i[2 ]), (255 , 255 , 0 ), 1 ) cv.circle(img, (int (i[0 ]), int (i[1 ])), 2 , (0 , 255 , 255 ), 2 ) except TypeError: print ('no Number' ) plt.subplot(121 ), plt.imshow(gray, cmap='gray' ), plt.axis('off' ) plt.subplot(122 ), plt.imshow(img, cmap='gray' ), plt.axis('off' ) plt.show()
■(十七)图像提取
【前景与背景】 cv.distanceTransform()【计算二值图中白色到黑色的距离】
cv.DIST_USER (自定义距离)
cv.DIST_L2 (欧几里得距离)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 img = cv.imread(pa.join(res, 'Images/zt.jpg' ), 1 ) imgrgb = cv.cvtColor(img, cv.COLOR_BGR2RGB) gray = cv.cvtColor(imgrgb, cv.COLOR_RGB2GRAY) ret, thresh = cv.threshold(gray, 150 , 255 , cv.THRESH_BINARY) kernel = np.ones((3 , 3 ), dtype=np.uint8) openex = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel, iterations=2 ) backward = cv.dilate(openex, kernel, iterations=3 ) dist = cv.distanceTransform(openex, cv.DIST_L2, 5 ) ret2, forward = cv.threshold(dist, 0.1 * dist.max (), 255 , 0 ) forward = np.uint8(forward) un = cv.subtract(backward, forward) retMark, markers = cv.connectedComponents(forward) markers = markers + 1 markers[un == 255 ] = 0 plt.subplot(241 ), plt.imshow(imgrgb, cmap='gray' ), plt.axis('off' ), plt.title('RGB/Original' ) plt.subplot(242 ), plt.imshow(openex, cmap='gray' ), plt.axis('off' ), plt.title('Threshold/Open' ) plt.subplot(243 ), plt.imshow(backward, cmap='gray' ), plt.axis('off' ), plt.title('BackGround/Dilate' ) plt.subplot(244 ), plt.imshow(dist, cmap='gray' ), plt.axis('off' ), plt.title('Distance/Open' ) plt.subplot(245 ), plt.imshow(forward, cmap='gray' ), plt.axis('off' ), plt.title('Distance/Threshold' ) plt.subplot(246 ), plt.imshow(markers, cmap='gray' ), plt.axis('off' ), plt.title('markers' ) plt.subplot(247 ), plt.imshow(un, cmap='gray' ), plt.axis('off' ), plt.title('Uncertain' ) plt.show()
【分水岭算法】 cv.connectedComponents()【二值图标注相连部分为同一色阶】
cv.watershed()【分水岭算法】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 img = cv.imread(pa.join(res, 'Images/zt.jpg' ), 1 ) imgrgb = cv.cvtColor(img, cv.COLOR_BGR2RGB) gray = cv.cvtColor(imgrgb, cv.COLOR_RGB2GRAY) ret, thresh = cv.threshold(gray, 150 , 255 , cv.THRESH_BINARY) kernel = np.ones((3 , 3 ), dtype=np.uint8) openex = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel, iterations=2 ) backward = cv.dilate(openex, kernel, iterations=3 ) dist = cv.distanceTransform(openex, cv.DIST_L2, 5 ) ret2, forward = cv.threshold(dist, 0.1 * dist.max (), 255 , 0 ) forward = np.uint8(forward) unknown = cv.subtract(backward, forward) retMark, markers = cv.connectedComponents(forward) markers = markers + 1 markers[unknown == 255 ] = 0 imgws = imgrgb.copy() waterShed = cv.watershed(imgws, markers.copy()) imgws[waterShed == -1 ] = [255 , 255 , 0 ] plt.subplot(241 ), plt.imshow(imgrgb, cmap='gray' ), plt.axis('off' ), plt.title('RGB/Original' ) plt.subplot(242 ), plt.imshow(openex, cmap='gray' ), plt.axis('off' ), plt.title('Threshold/Open' ) plt.subplot(243 ), plt.imshow(backward, cmap='gray' ), plt.axis('off' ), plt.title('Backward/Dilate' ) plt.subplot(244 ), plt.imshow(dist, cmap='gray' ), plt.axis('off' ), plt.title('Distance/Open' ) plt.subplot(245 ), plt.imshow(forward, cmap='gray' ), plt.axis('off' ), plt.title('Forward/Threshold' ) plt.subplot(246 ), plt.imshow(unknown, cmap='gray' ), plt.axis('off' ), plt.title('Backward - Forward' ) plt.subplot(247 ), plt.imshow(markers, cmap='gray' ), plt.axis('off' ), plt.title('markers' ) plt.subplot(248 ), plt.imshow(imgws, cmap='gray' ), plt.axis('off' ), plt.title('WaterShed' ) plt.show()
【方框前景提取】 cv.grabCut()【前景提取】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 img = cv.imread(pa.join(res, 'Images/yw.png' ), 1 ) imgrgb = cv.cvtColor(img, cv.COLOR_BGR2RGB) mask = np.zeros(img.shape[:2 ], dtype=np.uint8) bgModel = np.zeros((1 , 65 ), dtype=np.float64) fgModel = np.zeros((1 , 65 ), dtype=np.float64) border = 1 rectBorder = (border, border, img.shape[1 ]-border*2 , img.shape[0 ]-border*2 ) mask, bg, fg = cv.grabCut(img, mask, rectBorder, bgModel, fgModel, 10 , cv.GC_INIT_WITH_RECT) mask2 = np.where((mask == 2 ) | (mask == 0 ), 0 , 1 ).astype('uint8' ) cut = img * mask2[:, :, np.newaxis] cut = cv.cvtColor(cut, cv.COLOR_BGR2RGB) plt.subplot(141 ), plt.imshow(imgrgb) plt.subplot(142 ), plt.imshow(mask, cmap='gray' ) plt.subplot(143 ), plt.imshow(mask2, cmap='gray' ) plt.subplot(144 ), plt.imshow(cut) plt.show()
【交互式前景提取】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 img = cv.imread(pa.join(res, 'Images/yw.png' ), 1 ) imgrgb = cv.cvtColor(img, cv.COLOR_BGR2RGB) mask = np.zeros(img.shape[:2 ], dtype=np.uint8) bgModel = np.zeros((1 , 65 ), dtype=np.float64) fgModel = np.zeros((1 , 65 ), dtype=np.float64) border = 1 rectBorder = (border, border, img.shape[1 ]-border*2 , img.shape[0 ]-border*2 ) mask, bg1, fg1 = cv.grabCut(img, mask, rectBorder, bgModel, fgModel, 10 , cv.GC_INIT_WITH_RECT) maskcut = cv.imread(pa.join(res, 'Images/yw_cut.png' ), 0 ) mask[maskcut == 0 ] = 0 mask[maskcut == 255 ] = 1 mask, bg2, fg2 = cv.grabCut(img, mask, None , bgModel, fgModel, 10 , cv.GC_INIT_WITH_MASK) mask2 = np.where((mask == 2 ) | (mask == 0 ), 0 , 1 ).astype('uint8' ) cut = img * mask2[:, :, np.newaxis] cut = cv.cvtColor(cut, cv.COLOR_BGR2RGB) plt.subplot(241 ), plt.imshow(imgrgb) plt.subplot(242 ), plt.imshow(maskcut, cmap='gray' ) plt.subplot(243 ), plt.imshow(mask, cmap='gray' ) plt.subplot(244 ), plt.imshow(mask2, cmap='gray' ) plt.subplot(245 ), plt.imshow(cut) plt.show()
■(十八)视频处理 【主要函数】 cv.VideoCapture()【视频类构造】
cv.VideoCapture.isOpened【初始化是否成功】
cv.VideoCapture.open()【打开视频】
cv.VideoCapture.read()【读取视频信息】
cv.VideoCapture.release()【释放视频类】
cv.VideoCapture.get()【获取属性】
cv.VideoCapture.set()【设置属性】
cv.VideoCapture.grab()【指向下一帧】
cv.VideoCapture.retrieve()【解码本帧】
cv.VideoWriter()【视频写入类构造】
cv.VideoWriter_fourcc()【指定视频编码格式】
cv.VideoWriter.write()【写入下一帧视频】
cv.VideoWriter.release()【释放视频写入类】
【视频处理模板】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import cv2 as cvimport numpy as npimport os.path as paimport matplotlib.pyplot as pltres = '../../AssetResources' cap = cv.VideoCapture(pa.join(res, 'Videos/video1.mp4' )) capResolution = (int (cap.get(3 )), int (cap.get(4 ))) resolution = capResolution fps = 30 cap.set (3 , resolution[0 ]), cap.set (4 , resolution[1 ]) fourcc = cv.VideoWriter_fourcc(*'DIVX' ) output = cv.VideoWriter(pa.join(res, 'Videos/video2.mp4' ), fourcc, 30 , resolution, isColor=True ) while cap.isOpened(): ret, frame = cap.read() if ret: frame = cv.flip(frame, 0 ) cv.imshow('frame' , frame) output.write(frame) c = cv.waitKey(fps) if c == 32 : break else : break cap.release() output.release() cv.waitKey(1 ) cv.destroyAllWindows()
【摄像头处理模板】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import cv2 as cvimport numpy as npimport os.path as paimport matplotlib.pyplot as pltres = '../../AssetResources' cap = cv.VideoCapture(0 ) capResolution = (int (cap.get(3 )), int (cap.get(4 ))) resolution = capResolution cap.set (3 , resolution[0 ]), cap.set (4 , resolution[1 ]) fourcc = cv.VideoWriter_fourcc(*'DIVX' ) output = cv.VideoWriter(pa.join(res, 'Videos/video2.mp4' ), fourcc, 30 , resolution, isColor=True ) while cap.isOpened(): ret, frame = cap.read() if ret: cv.imshow('frame' , frame) output.write(frame) c = cv.waitKey(1 ) if c == 32 : break else : break cap.release() output.release() cv.waitKey(1000 ) cv.destroyAllWindows()
■(十九)绘图交互 【绘图】 cv.line()【直线】
cv.rectangle()【矩形】
cv.circle()【圆形】
cv.ellipse()【椭圆】
cv.polylines()【多边形】
cv.putText()【文字】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 canvas = np.zeros((500 , 500 , 3 ), dtype=np.uint8) row, col = canvas.shape[:2 ] cv.line(canvas, (0 , 250 ), (500 , 250 ), (0 , 0 , 255 ), 1 , cv.LINE_AA) cv.line(canvas, (250 , 0 ), (250 , 500 ), (0 , 0 , 255 ), 1 , cv.LINE_AA) cv.rectangle(canvas, (125 , 125 ), (375 , 375 ), (0 , 0 , 255 ), 1 , cv.LINE_AA) cv.circle(canvas, (250 , 250 ), 125 , (0 , 0 , 255 ), 1 , cv.LINE_AA) cv.ellipse(canvas, (250 , 250 ), (250 , 125 ), 90 , 0 , 360 , (0 , 0 , 255 ), 1 , cv.LINE_AA) points = np.array([[[250 , 0 ]], [[500 , 250 ]], [[250 , 500 ]], [[0 , 250 ]]], dtype=np.int32) cv.polylines(canvas, [points], True , (0 , 0 , 255 ), 1 , cv.LINE_AA) cv.putText(canvas, 'HELLOWORLD' , (250 , 250 ), cv.FONT_HERSHEY_SIMPLEX, 1 , (0 , 0 , 255 ), 1 ) cv.imshow('canvas' , canvas)
【鼠标与键】 cv.setMouseCallback()【鼠标方法与窗口映射】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 startPoint = (0 , 0 ) endPoint = (0 , 0 ) def mouse_action (event, x, y, flags, param ): global startPoint, endPoint if event == cv.EVENT_LBUTTONDOWN: startPoint = (x, y) elif event == cv.EVENT_LBUTTONUP: endPoint = (x, y) cv.rectangle(img, startPoint, endPoint, (0 , 0 , 255 ), 1 , cv.LINE_AA) img = np.full((500 , 500 , 3 ), fill_value=0 , dtype=np.uint8) cv.namedWindow('win1' ) cv.setMouseCallback('win1' , mouse_action) while True : cv.imshow('win1' , img) if cv.waitKey(20 ) == 32 : break cv.destroyAllWindows()
【滑动条】 cv.createTrackbar()【滑动条创建】
cv.getTrackbarPos()【滑动条调用】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def change_color (pos ): r = cv.getTrackbarPos('R' , 'img' ) g = cv.getTrackbarPos('G' , 'img' ) b = cv.getTrackbarPos('B' , 'img' ) img[:, :, :] = [b, g, r] img = np.zeros((100 , 700 , 3 ), dtype=np.uint8) cv.namedWindow('img' ) cv.createTrackbar('R' , 'img' , 0 , 255 , change_color) cv.createTrackbar('G' , 'img' , 0 , 255 , change_color) cv.createTrackbar('B' , 'img' , 0 , 255 , change_color) while True : cv.imshow('img' , img) if cv.waitKey(1 ) == 32 : break cv.destroyAllWindows()