一、图片显示
1、img = cv2.imread('cat.jpg',cv2.IMREAD_GRAYSCALE) 或者 img = cv2.imread('cat.jpg',cv2.IMREAD_GRAYSCALE,0) # 读取灰度图片
2、img = cv2.imread('cat.jpg',cv2.cv2.IMREAD_COLOR) 或者 img = cv2.imread('cat.jpg',cv2.IMREAD_GRAYSCALE) # 读取彩色图片
3、cv2.imshow(name,img) # 显示图片
4、cv2.waitKey(1000) # 设置等待时间,0表示任意终止,时间为毫秒
5、cv2.destroyAllWindows() # 创建windows窗口显示
6、img.shape # 图像的大小,灰度图:(100,100),彩色图:(100,100,3)
7、img.size # 像素点大小
8、img.dtype # 图片数值类型(uint8)
9、img[50:200,100:400] # 截取图片区域
10、b,g,r =cv2.split(img) # 提取BGR颜色通道值
11、cv2.merge((b,g,r)) # 还原颜色通道
12、img.copy() # 图片的复制
13、cur_img[:,:,0] = 0 # 将R颜色通道的数值置为0
二、视频显示
1、vc = cv2.VideoCapture('test.mp4') # 读取视频
2、vc.isOpened() # 检查视频是否可以打开,打开为True
3、vc..release() # 视频结束播放
4、open, frame = vc.read() # 视频读取 open为布尔类型,frame为视频每一帧图片
5、cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) # 将视频每一帧置为灰度
三、图片边界填充
1、top_size,bottom_size,left_size,right_size= (500,0,500,500) # 指定上下左右的填充大小
2、cv2.copyMakeBorder(img,top=top_size, bottom=bottom_size, left=left_size, right=right_size,borderType=cv2.BORDER_REPLICATE) # 最边缘填充
3、cv2.copyMakeBorder(img, top=top_size, bottom=bottom_size, left=left_size, right=right_size,borderType=cv2.BORDER_REFLECT) # 反射填充 abc|ba
4、 cv2.copyMakeBorder(img, top=top_size, bottom=bottom_size, left=left_size, right=right_size, borderType=cv2.BORDER_REFLECT_101) # 反射填充 abc|ba
5、cv2.copyMakeBorder(img, top=top_size, bottom=bottom_size, left=left_size, right=right_size,borderType=cv2.BORDER_WRAP) # 外包装法 cde|abcde|abcde
6、cv2.copyMakeBorder(img, top=top_size, bottom=bottom_size, left=left_size, right=right_size,borderType=cv2.BORDER_CONSTANT) # 常值填充
四、图片数值变换
1、cv2.resize(img,(500,414)) # 变换图片的尺寸,或者倍数
2、cv2.add(img,img) # 图片相加
3、cv2.addWeighted(img0,0.8,img,0.5,0) # 图片融合 ,最后一个0代表亮度集微调
五、图片阈值与平滑处理
1、阈值处理
# ret ,dst = v2.threshold(img,thresh,maxval,type)
# ret = hresh,dst 为输出图,thresh 为阈值,maxval 为当像素超过或者小于阈值时是赋予的值,type 为操作类型
ret ,dst = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
# cv2.THRESH_BINARY 超过阈值取maxval,否则取0
ret, dst = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
# cv2.THRESH_BINARY_INV,超过阈值取0,否则取maxval
ret, dst = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
# cv2.THRESH_TRUNC 大于阈值的部分设为阈值,否则不变
ret, dst = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
# cv2.THRESH_TOZERO 大于阈值的部分不变,否则设为0 (暗的地方变得更暗)
ret, dst = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
# cv2.THRESH_TOZERO_INV 小于阈值的部分不变,否则设为0
2、滤波平滑处理
cv2.blur(img,(3,3))
# 均值滤波((3,3)卷积和越大越模糊),卷积和一般设置为奇数
cv2.boxFilter(img,-1,(3,3),normalize=False)
# -1代表颜色通道,(3,3)代表卷积和,normalize如果为True过255的数值都会进行处理,和均值效果一样,normalize如果为False过255就会取255
cv2.GaussianBlur(img, (3, 3),1)
# 高斯滤波(有远近权重)
median = cv2.medianBlur(img,5)
# 中值滤波
六、图像形态学操作
1、腐蚀操作
kernel = np.ones((2,2),np.uint8) # 腐蚀卷积盒大小(卷积盒越大,线条越细)或者:cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
cv2.erode(img,kernel,iterations=1) # 腐蚀操作,iterations代表腐蚀次数
2、膨胀操作
kernel = np.ones((2, 2), np.uint8) # 膨胀卷积盒大小(卷积盒越大,线条越粗)或者:cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
dilate = cv2.dilate(img,kernel,iterations=1)
3、膨胀腐蚀处理(开闭运算)
# 开运算、先腐蚀后膨胀
kernel = np.ones((2, 2), np.uint8) # 卷积盒大小,或者:cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
# 闭运算、先膨胀后腐蚀
kernel = np.ones((2, 2), np.uint8) # 卷积盒大小,或者:cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
opening = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
4、梯度计算(即是图像的一个减法)
# 原始输入-卷积盒
kernel = np.ones((20, 20), np.uint8) # 卷积盒大小,或者:cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
cv2.morphologyEx(img1,cv2.MORPH_GRADIENT,kernel) # 一般卷积盒大小为原图显示范围结果
# 礼帽 = 原始输入 - 开运算
kernel = np.ones((3, 3), np.uint8) # 卷积盒大小,或者:cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
tophat = cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
# 黑帽 = 闭运算 - 原始输入
kernel = np.ones((3, 3), np.uint8) # 卷积盒大小,或者:cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
七、图像梯度算法
1、sobel算子
# cv2.Sobel(src,ddpeth,dx,dy,ksize)
# ddpeth:图像的深度、dx、dy:水平竖直的方向,ksize:Sobel算子的大小,不建议都设为1整体计算
sobelx =cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) # CV_64F表示取值可为复数
sobelx =cv2.convertScaleAbs(sobelx) # 画出来是一个半圆,白-黑>0保留、黑-白<0需要做反转
convertScaleAbs也可以写成:
sobelx = np.absolute(sobelx)
(minVal, maxVal) = (np.min(sobelx), np.max(sobelx))
sobelx = (255 * ((sobelx - minVal) / (maxVal - minVal)))
sobelx= sobelx.astype("uint8")
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) # CV_64F表示取值可为复数
sobely = cv2.convertScaleAbs(sobely) # 画出来是一个半圆,白-黑>0保留、黑-白<0需要做反转
sobelxy =cv2.addWeighted(sobelx,0.5,sobely,0.5,0) # 设置权重进行叠加
2、scharr 算子
# scharr描绘边界更加细腻 将左右上下设置为10,四边角设置为3,
scharrx = cv2.Scharr(img1, cv2.CV_64F, 1, 0,) # CV_64F表示取值可为复数
scharrx = cv2.convertScaleAbs(scharrx) # 画出来是一个半圆,白-黑>0保留、黑-白<0需要做反转
scharry = cv2.Scharr(img1, cv2.CV_64F, 0, 1,) # CV_64F表示取值可为复数
scharry = cv2.convertScaleAbs(scharry) # 画出来是一个半圆,白-黑>0保留、黑-白<0需要做反转
scharrxy = cv2.addWeighted(scharrx, 0.5, scharry, 0.5, 0) # 设置权重进行叠加
3、laplace算子
# laplace (会把噪音点当做边界)将中间设置为-4,上下左右设置为1,四边角设置为0,用上下左右相加减去4倍的中间
laplace = cv2.Laplacian(img1,cv2.CV_64F,)
laplace = cv2.convertScaleAbs(laplace)
八、图像边缘
# cv2.Canny(img, minVal, maxVal)
# minVal和maxVal取值大则没有那么细致,将边边界置为白色
cv2.Canny(img, 50, 60)
九、图像轮廓
1、图像变换大小
cv2.pyrUp(img) # 向上采样(图像变大)
cv2.pyrDown(img) # 向下采样(图像变小)
2、轮廓检测
# cv2.findContours(img,mode,method)
# mode参数:
# RETR_EXTERNAL:只检索最外面的轮廓;
# RETR_LIST:检索所有的轮廓,并将其保存到一条链表中;
# RETR_CCOMP:检索所有的轮廓,并将他们组织为两层,顶层是各部分的外部边界,第二层是空洞边界;
# RETR_TREE:检索所有轮廓,并重构嵌套的整个层次(普遍用法)
# method参数
# CHAIN_APPROX_NONE:以freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)
# CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是说函数保留他们的重点部分
检测步骤:
# 将图片转成灰度图片
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 将图片进行阈值处理
ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
# 轮廓检测,contours为轮廓信息,hierarchy为图像层级
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
# 绘制轮廓图,draw_img为在图上画轮廓,contours为轮廓线条,-1(其他数字为取第所有数字轮廓)为取所有轮廓,(255,0,0)代表绘制颜色通道,2代表线条粗细
res = cv2.drawContours(draw_img,contours,-1,(255,0,0),2)
3、轮廓计算
cnt = contours[-1] # 取出某个轮廓
cv2.contourArea(cnt) # 计算面积
cv2.arcLength(cnt,True) # 计算周长,True表示闭合
4、轮廓近似
epslion = 0.01*cv2.arcLength(cnt,True) # epslion通常按照周长百分比设置
approx = cv2.approxPolyDP(cnt,epslion,True) # 算出近似轮廓
cv2.drawContours(img,approx,1,(255,0,0),2) # 在原图形上画出近似轮廓
5、轮廓外接矩形
x,y,w,h = cv2.boundingRect(cnt) # 根据轮廓得出外接矩形顶点、横纵加长坐标
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
6、轮廓外接圆形
(x,y),radius = cv2.minEnclosingCircle(cnt) # 根据轮廓得出外接圆圆心,半径
center = (int(x),int(y))
radius = int(radius)
cv2.circle(img,center,radius,(255,0,0),1)
7、模板匹配
# 匹配单个模板
# 进行模板匹配(这里输出的是经过匹配之后比较符合的二维数组点),假如原图形是AxB大小,而模板是axb大小,则输出结果的矩阵是(A-a+1)x(B-b-1)
res = cv2.matchTemplate(img,face,cv2.TM_CCOEFF_NORMED) # face与img进行匹配
# TM_SODIFF: 计算平方不可, 计算出来的值越小, 越相关
# TM_CCORR: 计算相关性, 计算出产的值越大, 越相关
# TM_CCOEFF: 计算相关系数, 计算出来的值越大, 越相关
# TM_SODIFF_NORMED: 计算归一化平方不同, 计算出来的值越接近0, 越相关
# TM_CCORR_NORMED: 计算归一化相关性, 计算出来的值越接近1, 越相关
# TM_CCOEFF_NORMED: 计算归一化相关系数, 计算出来的值越接近1, 越相关
# minMaxLoc找出其中的最小值,min_val为最小值,max_val为最大值,min_loc一般为右上角的位置(最小值位置),max_loc为最大值位置
min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(res)
bottom_right = (min_loc[0]+w,min_loc[1]+h) # 在原图上截取模板大小
res = cv2.rectangle(img,min_loc,bottom_right,(255,255,0),2) # 在原图上画出矩形
# 匹配多个模板
# 取匹配程度大于0.8的坐标
loc = np.where(res>= 0.8)
# zip将对象中对应的元素打包成一个个元组,*号代表可选参数
for pt in zip(*loc[::-1]):
cv2.rectangle(img1,min_loc,bottom_right,(255,255,0),2)
十、图像直方图
1、直方图
# cv2.calcHist(images,channels,mask,histSize,ranges)
# images:原图像图像格式为uint8或float32,当传入函数时应用中括号口括来例如[img]
# channels:同样用中括号括来它会告函数我们统幅图像的直方图。如果入图像是灰度图它的值就是[0如果是彩色图像的传入的参数可以是[0][1[2] 它们分别对应着BGR
# mask:掩模图像。统整幅图像的直方图就把它为None,但是如果你想统图像某一分的直方图的你就制作一个掩模图像并使用它。
# histsize:BIN的数目。也应用中括号括来
# ranges:像素值范围常为[0256]
calc = cv2.calcHist([img],[0],None,[255],[0,256])
2、各颜色通道直方图
colors = ('b', 'g', 'r')
chans = cv2.split(img) # 将三个颜色通道拆分,通过cv2.merge()合并
for (chan, color) in zip(chans, colors):
hist = cv2.calcHist([chan], [0], None, [256], [0, 256])
plt.plot(hist, color = color)
plt.xlim([0, 256])
3、直方图之mask(掩码)使用
master = np.zeros(img.shape[:2], np.uint8) # 将图像全部置为0
master[50:100, 100:200] = 255 # 将中心部分置为255(需要显示的部分)
maskimg = cv2.bitwise_and(img, img, mask=master) # 将掩码和原图像重合
hist_mask = cv2.calcHist([img], [0], maskimg, [255], [0, 255]) # 带入重合数据计算直方图
plt.plot(hist_mask)
十一、图像均衡化
1、均衡化
cv2.equalizeHist(img) # 直接去图像进行均衡化操作
plt .hist(img1.ravel(),256) # ravel()将高维数组转为一维数值
2、自适应均衡化
clahe = cv2.createCLAHE(clipLimit=10,tileGridSize=(8,8)) # lipLimit颜色对比度的阈值,tileGridSize每个格子的大小
res = clahe.apply(img) # 将结果赋予原图像
十二、傅里叶变换
1、傅里叶变换(得到亮度高在图像中间的图像)
# 执行傅里叶变换,opencv中主要就是cv2.dft()和cv2.idft(), 输入图像需要先转换成np.float32格式
img_float32 = np.float32(img)
dft = cv2.dft(img_float32,flags = cv2.DFT_COMPLEX_OUTPUT)
# 得到的结果中频率为0的部分会在左上角, 通常要转换到中心位置, 可以通过shift变换来实现。
dft_shift = np.fft.fftshift(dft)
# cv2.dft()返回的结果是双通道的(实部,虚部), 通常还需要转换成图像格式才能展示(0, 255)
res = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
plt.imshow(res,cmap='gray')
2、低通滤波(会使得图像变模糊)
img_float32 = np.float32(img)
dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
# 计算原图的中心位置
rows , cols = img.shape
crow , cclo = int(rows/2),int(cols/2)
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30,cclo-30:cclo+30] = 1
fshift = dft_shift*mask
# 得到的结果中频率为0的部分会在左上角, 通常要转换到中心位置,需要还原。
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
plt.imshow(img_back, cmap='gray')
plt.show()
3、高通滤波(只保留高频,会使得图像细节增强)
img_float32 = np.float32(img)
dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
# 计算原图的中心位置
rows, cols = img.shape
crow, cclo = int(rows / 2), int(cols / 2)
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow - 30:crow + 30, cclo - 30:cclo + 30] = 0
fshift = dft_shift * mask
# 得到的结果中频率为0的部分会在左上角, 通常要转换到中心位置,需要还原。
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])
plt.imshow(img_back, cmap='gray')