Opencv-Python笔记
注:Opencv读取图片的格式是BGR
- 数据读取——图像
① cv2.imread(‘参数1’,参数2) ——读取指定图像,参数1指图像名,参数2指图像格式,彩色or灰度注:cv2.IMREAD_COLOR ——彩色图像 cv2.IMREAD_GRAYSCALE ——灰度图像
② cv2.imshow(‘参数1’,参数2) ——显示图像 注:参数1指显示窗口名,可任意;参数2指需显示图像矩阵
③ cv2.waitKey(参数1);cv2.destroyAllWindows() ——等待时间,毫秒级,关闭显示窗口 注:参数1指毫秒数,若参数1等于0,则是按任意键关闭
④ cv2.imwrite(‘参数1’,参数2) ——保存 注:参数1指图像名或图像路径;参数2指图像矩阵数据
- 数据读取——视频
- cv=cv2.VideoCapture(‘’) ——读取指定路径下的视频流 注:cv2.VideoCapture()可捕获摄像头,0、1设定不同设备
- ##检查是否正确打开##
if vc.isOpened(): #视频流变量名.isOpened()
open, frame = vc.read() #open被赋予布尔值;frame被赋予某帧图像的矩阵值
else:
open = Flase
while open:
ret, frame = vc.read() #ret被赋予布尔值;
if frame is None: #若某帧图像是空白,则会退出完成
Break;
if ret == True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # BGR2GRAY是指B、G、R三个通道顺序
cv2.imshow(‘result’,gray)
if cv2.waitKey(100) & 0xFF == 27: #0xFF是指Esc键
break
vc.release()
cv2.destroyAllWindows()
- 颜色通道提取
① b,g,r=cv2.split(图像矩阵变量名)
② cv2.merge((b, g, r)) ——图像通道重新组合
③ 若需只要一个通道的来显示图像,则可将其余两通道设为0
例如:###只保留R通道###
A_img = img.copy() #复制img图像数据矩阵赋予A_img
A_img[: , : , 0]=0 #通道0数据均赋予0
A_img[: , : , 1]=0 #通道1数据均赋予0
cv_show(‘R’, A_img)
- 边界填充
top_size,bottom_size,left_size,right_size = (a, b, c, d)
img_name = cv2.copyMakeBorder(参数1,top_size, bottom_size, left_size, right_size, borderType=参数2 ) 注:参数1是指需进行边界填充的图像数据矩阵;参数2是指填充的类型,如下是填充类型:
BORDER_REPLICATE :复制法,及复制图像最边缘像素
BORDER_REFLECT :反射法,及对感兴趣的图像中的像素在两边进行复制,eg: fedcba|abcdefgh|hgfedc
BORDER_REFLECT_101 :反射发,及以最边缘像素为轴,对称,eg:hgfedcb|abcdefgh|gfedcba
BORDER_WRAP :外包装法 eg: bcdefgh|abcdefgh|abcdefg
BORDER_CONSTANT :常量法,常数值填充 img_name = cv2.copyMakeBorder(参数1,top_size, bottom_size, left_size, right_size, borderType=参数2 ,value=number)
- 数值计算(像素值范围为0~255,共256个值)
① cv2.add(图像1矩阵,图像2矩阵) 注:若图像1与图像2对应元素相加大于255,,则定值为255
② 图像3矩阵 = 图像1矩阵 + 图像2矩阵 注:若图像1与图像2对应元素相加大于255,,则定值为与256的差值
- 图像融合(需确保图像大小一致)
- cv2.resize() ——重置图像的大小
用法1:cv2.resize(图像,(数值1,数值2)) ——将图像重置为数值1 × 数值2的图像
用法2:cv2.resize(图像,(0,0),fx=a,fy=b) ——将图像重置为x轴为a倍,y轴为b倍的图像
② cv2.addWeighted(图像1,a,图像2,b,c) ——权重为a的图像1,与权重为b的图像2,且偏置为b进行融合 注:偏置b可理解为输出提亮
- 图像阈值
ret, dst = cv2.threshold(src, thresh, maxval, type)
其中:ret ——输出的阈值; dst ——输出图; src ——输入图; thresh ——阈值;
maxval ——当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值;
type ——二值化操作的类型,如下:
cv2.THRESH_BINARY 超过阈值部分取maxval,否则取0
cv2.THRESH_BINARY_INV 指cv2.THRESH_BINARY 的反转
cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0
cv2.THRESH_TOZERO_INV 指cv2.THRESH_TOZERO 的反转
- 图像平滑处理
①均值滤波 cv2.blur(图像矩阵,(a,b)) 注:(a,b)指大小为a×b的卷积核,各元素值均为1
②方框滤波 cv2.boxFilter(图像矩阵,-1,(a,b),normalize=True/False) 注:True是选择做归一化,Flase是选择不做规一化
③高斯滤波 cv2.GaussianBlur(图像矩阵,(a,b),1) 注:(a,b)指大小为a×b的卷积核,各元素值与据均值距离成反比
④中值滤波(将中间值作为输出值) cv2.medianBlur(图像矩阵,a) 注:a指Fliter的大小
- 形态学—腐蚀操作
cv2.erode(图像矩阵,腐蚀核大小,iterations = a) 注:iterations指迭代次数,即腐蚀次数;腐蚀核指大小为b×c的矩阵,元素均能为1
腐蚀核Eg:kernel=np.ones((5,5),np.uint8)
- 形态学—膨胀操作
cv2.dilate(图像矩阵,膨胀核大小,iterations = a)
- 开运算与闭运算
①开运算 cv2.morphologyEx(图像矩阵,cv2.MORPH_OPEN,核大小) #先腐蚀,后膨胀
②闭运算 cv2.morphologyEx(图像矩阵,cv2.MORPH_CLOSE,核大小) #先膨胀,后腐蚀
- 梯度计算 #梯度=膨胀 - 腐蚀
cv2.morphologyEx(图像矩阵,cv2.MORPH_GRADIENT,核大小)
- 礼帽与黑帽
①礼帽 cv2.morphologyEx(图像矩阵,cv2.MORPH_TOPHAT,核大小) #礼帽 = 原始输入 - 开运算结果
②黑帽 cv2.morphologyEx(图像矩阵,cv2.MORPH_BLACKHAT,核大小) #黑帽 = 闭运算 - 原始输入
- 图像梯度——Sobel算子
(注:x、y轴需分开操作后再进行求和操作,否则结果会出现错误,求和使用cv2.addWeighted()函数)
3阶算子:
dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
dst = cv2.convertScaleAbs(dst)
其中:src指输入图像矩阵;
ddepth指图像的深度(可理解为数据类型),-1表示与原图像同样深度;
dx与dy分别指水平方向和垂直方向,dx=1、dy=0时求x轴(左右)方向,dx=0、dy=1时求y轴(上下)方向;
ksize指Sobel算子大小,默认为3;
注:求出的dst中的存在部分元素为负数,则会出现错误结果,即白到黑为正数,黑到白为负数,所有负数会被截断成0(黑色),故需取绝对值,及使用cv2.convertScaleAbs()函数进行转换dst,随后再打印结果。
- 图像梯度——Scharr、laplacian算子(绝对值操作)
①Scharr算子(较Sobel算子的元素值大,故分割结果更细致明显)
3阶算子:
cv2.Scharr(src, ddepth, dx, dy)
②laplacian算子 (对噪音点较敏感,需与其他算法结合使用)
转存失败重新上传取消
cv2.laplacian(src,ddepth)
- Canny边缘检测
步骤:
1)使用高斯滤波器(归一化处理),用来平滑图像,滤除噪音;
2)计算图像中每个像素点的梯度强度和方向(Sobel算子),
强度: 方向:;
3)应用非极大值抑制,以消除边缘检测带来的杂散响应;
4)应用双阀值检测确定真实的和潜在的边缘;
梯度值>maxVal:则处理为边界;
minVal<梯度值<maxVal:连有边界则保留,否则舍弃;
梯度值<minVal:则舍弃。
- 通过抑制孤立的弱边缘最终完成边缘检测;
cv2.Canny(图像矩阵,minVal,maxVal) 注:minVal值越小,边缘检测结果越细致
- 图像金字塔
①高斯金字塔
向下采样方法(缩小) cv2.pyrDown(图像矩阵)
向上采样方法(放大) cv2.pyrUp(图像矩阵)注:将图像在每个方向扩大为原来的两倍,新增的行与列以0填充,使用先前同样的内核(乘以4)放大后的图像卷积
②拉普拉斯金字塔
- 图像轮廓
cv2.findContours(img,mode,method)
其中:mode轮廓检索模式:
cv2.RETR_EXTERNAL:只检索最外面的轮廓;
cv2.RETR_LIST:检索所有的轮廓,并将其保存到一条链表中;
cv2.RETR_CCOMP:检索所有的轮廓,并将他们组织为两层,顶层是各部分的外部边界,第二层是空洞的边界;
cv2.RETR_TREE(最常用):检索所有轮廓,并重构嵌套轮廓的整个层次;
method轮廓逼近方法:
cv2.CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列);
cv2.CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,即函数只保留他们的终点部分;
使用步骤:
img = cv2.imread(‘输入图像’)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转化为灰度图像
ret, thresh = cv2.threshhold(gray,127,255,cv2.THRESH_BINARY)
binary,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
(注:binary指图像的二值结果;contours指图像轮廓信息;hierarchy是指层级)
###绘制轮廓###
draw_img = img.copy() (注:必须进行图像的copy,否则标注完后,原始图片会变成标注完成的图像)
res = cv2.drawContours(draw_img, contours, -1, (0,0,255), 2)
(注:contours指标注信息;-1指全部轮廓,也可设为0、1、2... ;(0,0,255)/(B,G,R)指标注线为红色R,或可换为蓝色B、绿色G;2是指标注线宽度)
轮廓特征
变量1 = contours[num] #将第num个轮廓数据赋予变量1
#面积 cv2.contourArea(变量1)
#周长 cv2.arcLength(变量1,True) #True指轮廓是闭合的
轮廓近似
epsilon = num*cv2.arcLength(变量1,True) #num越小,轮廓越近似,epsilon亦可直接赋值
cv2.approxPolyDP(变量1,epsilon,True)
边界矩形
x,y,w,h = cv2.boundingRect(图形轮廓)
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
外界圆
(x,y),radius = cv2.minEnclosingCircle(图形轮廓)
center = (int(x),int(y))
radius = int(radius)
cv2.circle(img,center,radius,(0,255,0),2)
- 模板匹配
模板匹配和卷积原理相似,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度,这个差别程度的计算方法在opencv中有6种,然后将每次计算的结果放在一个矩阵里,作为结果输出。若原图像大小为A*B,模板大小为a*b,则输出结果的矩阵大小为(A-a+1)*(B-b+1)。
差别程度计算方法(平常尽量使用归一化的方法):
cv2.TM_SQDIFF:计算平方不同,计算出来的值越小,越相关;
cv2.TM_CCORR:计算相关性,计算出来的值越大,越相关;
cv2.TM_CCOEFF:计算相关系数,计算出来的值越小,越相关;
cv2.TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关;
cv2.TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关;
cv2.TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关;
变量1 = cv2.matchTemplate(原图像矩阵,模板矩阵,计算方法)
min_val, max_val, min_loc, max_loc = cv2.minMaxloc(变量1)
注:若需进行多对象匹配,则可设定一个阈值,比较其与差别程度的计算大小,从而得到满足条件的location,再循环画出矩形框。
- 傅里叶变换
傅里叶变换的作用
高频——变化剧烈的灰度分量,例如边界;
低频——变化缓慢的灰度分量,例如一片大海;
滤波
低通滤波器:只保留低频,会使图像模糊;
高通滤波器:只保留高频,会使图像变得细节增强;
注:opencv中主要是cv2.dft()和cv2.idft(),输入图像需先转换成np.float32格式——np.float32(输入图像);
得到的结果中频率为0的部分会在左上角,通常需要shift将其转换到中心位置;
cv2.dft()返回的结果是双通道的(实部、虚部),通常需转换成图像格式显示(0,255)
重要程序:
img = cv2.imread(‘输入图像’,0)
img_float32 = np.float32(img)
#DFT#
dft = cv2.dft(img_float32, cv2.DFT_COMPLEX_OUTPUT)
注:cv2.DFT_COMPLEX_OUTPUT指进行傅里叶变换的方法
dft_shift = np.fft.fftshift(dft)
#得到灰度图能表示的形式#
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
注:cv2.magnitude(x,y)将实部和虚部投影到空间域
#得到中心点位置#
rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2)
#低通滤波#
mask_l = np.zeros((rows, cols, 2), np.uint8)
mask_l[crow-30:crow+30, ccol-30:ccol+30] = 1
#高通滤波#
mask_h = np.ones((rows, cols, 2), np.uint8)
mask_h[crow-30:crow+30, ccol-30:ccol+30] = 0
#IDFT#
fshift = dft_shift*mask_l
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
- 直方图
cv2.calcHist(images, channels, mask, histSize, ranges) ——统计各个像素值的个数分布
其中:
images——原图像图像格式为uint8或float322,当输传入函数时,应用中括号[]括起来
channels——当输传入函数时,应用中括号[]括起来,其会告诉函数我们整幅图像的直方图,若输入图像时灰度图时,则值为[0],若是彩色图像(BGR),则传入参数是[0][1][2];
mask——掩模图像,统整整幅图像的直方图,则设值为None,但若想统图像某一份的直方图,则需制作一个掩膜图像使用;
mask操作步骤
mask = np.zeros(img.shape[:2], np.uint8) #生成与原图像一样大的0矩阵
mask[num1:num2, num3:num4] = 255 #将目标部分设为白色
masked_img = cv2.bitwise_and(img, img, mask=mask) #与操作,将掩码图像与原图像结合在一起
hisSize——BIN的数目,亦用中括号[]括起来;
ranges——像素值范围常为0~256,亦用中括号[]括起来;
直方图均衡化
cv2.equalizeHist(输入图像)
自适应直方图均衡化
clahe = cv2.createCLAHE(clipLimit=num1, titleGridSize=(num2,num3)) #实例化自适应直方图均衡化函数
注:clipLimit指颜色对比度的阈值;titleGridSize指将原图像分为num2*num3大小的网格进行均衡化操作
变量 = clahe.apply(输入图像) #进行自适应直方图均衡化
- 图像特征——harris角点检测
角点——某块区域的像素点在X、Y轴方向上滑动,其像素值变化很快;
cv2.corerHarris(img, blockSize, ksize, k)
其中:img ——数据类型为float32的输入图像;
blockSize ——角点检测中指定区域的大小;
ksize ——Sobel求导中使用的窗口大小;
k ——取值参数为[0.04,0.06]
- Scale Invariant Feature Transform(SIFT) ??? ——一种特征匹配算法
sift = cv2.xfeatures2d.SIFT_create() #sift实例化
kp = sift.detect(输入灰度图像, None) #得到关键点
img = cv2.drawKeypoints(输入灰度图像, kp, 输入原始图像)