Open CV
第一章图像基本操作
分辨率:衡量数字图像、显示设备或打印品细节丰富程度的核心指标,本质是‘单位长度/区域内的最小信息单元数’
位图:由无数个独立的像素点按行列排列组成的图像类型,是照片、手机/相机拍摄图、网络图片等主要格式(JPG\PNG…)
像素点:构成位图的最小基本单元,每个像素点都包含独立的颜色和亮度信息,大量像素点按行排列,共同组成人眼可见的完整图像
像素点=屏幕长度/对应方向像素数
像素点的颜色:主要由颜色模型来定义,核心是用特定数值组合描述红、绿、蓝等基础色的亮度比例
RGB模型:提供红绿蓝三种基础色的不同强度组合,来表示几乎所用可见颜色的模型。在数字图像里,每个像素的颜色都由这三个通道的数值决定
OpenCV中图像默认BGR顺序通道存储
通道索引规则:三个通道的索引蓝0、1绿、2红
保留蓝色通道,则将R、G通道的像素值设为0
适用OpenCV读取图像后,若图像是RGB模型,则使用cv2.cvtColor函数进行通道转化
基本操作
cv2:计算机视觉领域的核心库,提供了大量用于图像处理、计算机视觉的函数接口。
如cv2.imread:读取图像文件,将图像以数组形式加载到程序中
cv2.imshow():用于显示图像
cv2.waitKey():控制图像显示的等待时间
cv2.destroyALLWindows():关闭私有显示图像的窗口
numpy:Python中用于数值计算的基础库,尤其擅长处理多维数组
在图像处理中cv2读取的图像本质是numpy的多维数组[彩色图像:高维度,宽度,通道数]
可以利用numpy对图像数组进行各种数字运算,比如修改像素值、对图像区域进行切片操作…
Matplotlib:Python的绘图库,主要用于数据可视化
在图像处理中,可以用来绘制图像,
如matplotlib.pyplot.imshow()显示图像
【图像的读取、显示:cv2
图像的处理:numpy
图像的可视化操作:matplotlib】
数据读取—图像
cv2.IMREAD_COLOR: 彩色图像
cv2.IMREAD_GRAYSCALE:灰度图像
#示例
#引入Python库
import cv2
import numpy
import matplotlib
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\google.jpg")
print(img)#读取到多维数组
#显示图像,也可以创建多个窗口
cv2.imshow(‘image’,img)#第一个参数随意,第二个参数传入图像名字
#等待时间,毫秒级,0表示任意键终止
cv2.waitKey(0)#0:按下任意键就消失
cv2.destroyAllWindows()
#灰度设置
img=cv2.imread(r"C:\Users\19022\Desktop\google.jpg",cv2.IMREAD_GRAYSCALE)
#保存
#cv2.imwrite(‘’,img)#路径,图片名称
#图像类型
print(type(img))
#图像像素点的计算
print(img.size)
数据读取—视频
cv2.VideoCapture:可以捕获摄像头,用数字来控制不同的设备,例如0,1
如果是视频文件,直接指定好路径即可
ROI区域
Region of Interest,感兴趣区域
在图像处理、计算机视觉等领域中,从图像/视频里专门圈选处理需要重点处理或分析的特定区域
聚焦关键部分,只对ROI内进行像素计算,减少不必要运算
截取部分图像数据
#示例
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\google.jpg")
#对图像进行切片操作
img1=img[0:500,0:200]#截取高度500像素,宽度200像素
cv2.imshow(‘wew’,img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
颜色通道提取
#示例
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\google.jpg")
#将颜色通道分隔开
b,g,r=cv2.split(img)
print(b)
print(b.shape)#获取图像的形状信息,返回值为元组
print(g)
print®
#将颜色通道合起来
img1=cv2.merge((b,g,r))
print(img1)
print(img1.shape)
#RGB全部保留图像
img=cv2.imread(r"C:\Users\19022\Desktop\google.jpg")
cv2.imshow(‘ss’,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#只保留R图像
cur_img=img.copy()#复制图像数组,创建一个图像深拷贝
cur_img[:,:,0]=0
cur_img[:,:,1]=0
cv2.imshow(‘G’,cur_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#只保留G
cur_img=img.copy()
cur_img[:,:,0]=0
cur_img[:,:,2]=0
cv2.imshow(‘G’,cur_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#只保留B
cur_img=img.copy()
cur_img[:,:,1]=0
cur_img[:,:,2]=0
cv2.imshow(‘G’,cur_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
边界填充
BORDER_REPLICATE:复制法,复制图像最边缘像素
BORDER_REFLECT:反射法,对ROI的图像中的像素在两边进行复制
BORDER_REFLECT_101:反射发,以最边缘像素为轴,对称
BORDER_WRAP:外包装法
BORDER_CONSTANT:常量法,常数值填充
#示例
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\google.jpg")
#边界填充
top_size,bottom_size,left_size,right_size=(50,50,50,50)
reprlicate=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REPLICATE)
reflect=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_REFLECT)
reflect101=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_REFLECT_101)
wrap=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_WRAP)
constant=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_CONSTANT,value=0)
#########
plt.subplot(231),plt.imshow(img,‘gray’),plt.title(‘ORIGINAL’)
plt.subplot(231),plt.imshow(img,‘gray’),plt.title(‘REPLICATE’)
plt.subplot(233),plt.imshow(reflect,‘gray’),plt.title(‘REFLECT’)
plt.subplot(234),plt.imshow(constant,‘gray’),plt.title(‘REFLECT_101’)
plt.subplot(235),plt.imshow(wrap,‘gray’),plt.title(‘WRAP’)
plt.subplot(236),plt.imshow(constant,‘gray’),plt.title(‘CONSTANT’)
plt.show()
数值计算
#示例
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\cat.jpg")
img2=cv2.imread(r"C:\Users\19022\Desktop\dog.jpg")
#对img上的每个像素的所有通道都加上10
img_cat=img +10
#提取所有列,前5行,第0通道的像素值
img[:5:,0]
#输出
print(img[:5:,0])
print(img_cat[:5:,0])
print(cv2.add(img,img_cat)[:5,:,0])#出现溢出取255
print((img_cat+img)[:5:,0])#出现溢出取溢出
图像融合
要求融合的图片必须尺寸完全相同
#示例
#读取图像,设置相同尺寸
img=cv2.imread(r"C:\Users\19022\Desktop\cat.jpg")
img=cv2.resize(img,(600,400))#resize调整图像尺寸
img2=cv2.imread(r"C:\Users\19022\Desktop\dog.jpg")
img2=cv2.resize(img2,(600,400))
#加权融合
res=cv2.addWeighted(img,0.8,img2,0.6,0)#addWeighted对两张相同尺寸的图像进行加权融合
#输出图像
cv2.imshow(‘ew’,res)
cv2.waitKey(0)
cv2.destroyAllWindows()
第二章阈值与平滑处理
阈值:将图像转化为更简单的二值图像(只要黑白两种像素),或对图像进行分割、筛选等操作
设定一个阈值,像素值大于阈值,归为一类
像素值小于阈值,归为一类
图像阈值
阈值是图像分割技术,通过设定一个固定阈值,将图像的像素灰度值与阈值比较,将像素分为两类(前景/背景),生成二值化图像
ret,dst=cv2.threshold(src,thresh,maxval,type)
cv2.threshold:实现阈值操作的核心函数
dst:输出图
Ssrc:输入图,只能输入单通道图像,通常来说为灰度图
threesh:阈值
maxval:当像素值超过或小于阈值部分,根据type决定,所赋予的值
type:二值化操作,包含以下5种类型:
cv2.THRESH_TOZERO_INV
cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
cv2.THRESH_BINARY_IN VTHRESH_BINARY的反转
cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
cv2.THRESH_TOZERO 大于阈值部分不变,否则设为0
cv2.THRESH_TOZERO_INV THRESH_TOZERO反转
图像平滑处理
滤波
滤波主要是利用滤波器对图像进行处理,达到减少图像噪声、模糊图像细节等平滑图像的目的
图像是二维的离散信号,滤波操作本质通过滤波器与图像进行卷积运算。
滤波器在图像上逐点滑动,在每个位置上,滤波器与图像对应区域的像素值进行加权求和,得到该位置滤波后的新像素值,从而达到改变图像像素分别,实现平滑效果
滤波器
一种用于修改或增强图像的工具,通过特定的算法改变图像中像素值
卷积
卷积运算是滤波器与图像进行逐点加权求和的操作,是实现平滑、边缘检测等多数滤波效果的数学工具,通过‘局部区域加权’来改变图像像素值,突出抑制特定特征
【卷积:用滤波器在图像上扫一遍,每扫到一个位置:对齐—相乘—求和】
均值滤波
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")#读取图像
blur=cv2.blur(img,(3,3))
cv2.imshow(‘s’,blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
方框滤波
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")#读取图像
blur=cv2.boxFilter(img,-1,(3,3),normalize=True)
cv2.imshow(‘s’,blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
高斯滤波
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")#读取图像
blur=cv2.GaussianBlur(img,(5,5),1)
cv2.imshow(‘s’,blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
中值滤波
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")#读取图像
blur=cv2.medianBlur(img,5)
cv2.imshow(‘s’,blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
第三章图像形态学操作
morphologyEx是执行高级形态学变换的函数,能实现腐蚀、膨胀、开运算、闭运算、礼帽、黑帽运算等多种操作
morphologyEx(输入的图像,进行的形态学操作,结构元素)
进行形态学的操作:
Cv2.MORPH_ERODE:腐蚀
Cv2._MORPH_DILATE:膨胀
Cv2.MORPH_OPEN:开运算
Cv2.MORPH_CLOSE:闭运算
Cv2.MORPH_TOPHAT:礼帽运算
Cv2.MORPH_BLACKHAT:黑帽运算
腐蚀操作
腐蚀
‘收缩’图像的前景区域(通常为白色目标),通过消除前景边缘的像素,达到去除小噪声、细化目标轮廓或分离相邻目标的效果
前景区域
关注的、需要处理的目标区域。通常通过像素值区分(白色前景,黑色背景,反之)
#示例
import cv2
import matplotlib
import numpy as np
from cv2.gapi import kernel
img=cv2.imread(r"C:\Users\19022\Desktop\tup.jpg")
kernel=np.ones((5,5),np.uint8)#创建结构元素
腐蚀操作需要结构元素,用numpy.ones函数创建一个55全为1的数组,数据类型为np.uint8无符号8位整数。这个数组会在腐蚀是以55的窗口在图像上滑动进行操作
erosion=cv2.erode(img,kernel,iterations=1)#腐蚀处理
Cv2.erode函数用于对图像进行腐蚀操作,(预处理的图像名,结构元素,腐蚀执行次数)
#图像处理
cv2.imshow(‘ss’,erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
膨胀操作
#示例
#模块导入
import cv2
import matplotlib
import numpy as np
from cv2.gapi import kernel
#图像地址
img=cv2.imread(r"C:\Users\19022\Desktop\tup.jpg")
#创建结构元素
ker2=np.ones((3,3),np.uint8)
#膨胀操作
res1=cv2.dilate(res,ker2,iterations=1)
#图像展示
cv2.imshow(‘s’,res1)
cv2.waitKey(0)
cv2.destroyAllWindows()
开运算与闭运算
开:先腐蚀,后膨胀
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\tup.jpg")
#结构元素
ker=np.ones((5,5),np.uint8)
#先腐蚀后膨胀
opening=cv2.morphologyEx(img,cv2.MORPH_OPEN,ker)
#图片展示
cv2.imshow(‘d’,opening)
cv2.waitKey(0)
cv2.destroyAllWindows()
闭:先膨胀,后腐蚀
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\tup.jpg")
#结构元素
ker=np.ones((5,5),np.uint8)
#先膨胀后腐蚀
closing=cv2.morphologyEx(img,cv2.MORPH_CLOSE,ker)
#图像展示
cv2.imshow(‘d’,closing)
cv2.waitKey(0)
cv2.destroyAllWindows()
礼帽和黑帽
礼帽=原始输入-开运算结束
原始输入:在进行开运算操作之前的原始图像
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\tup.jpg")
ker=np.ones((5,5),np.uint8)#创建结构元素
#进行开运算
opening=cv2.morphologyEx(img,cv2.MORPH_OPEN,ker)
#礼帽运算
tophat=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,ker)
cv2.imshow(‘d’,tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()
黑帽:闭运算-原始输入
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\tup.jpg")
ker=np.ones((5,5),np.uint8)
closing=cv2.morphologyEx(img,cv2.MORPH_CLOSE,ker)
blackhat=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,ker)
cv2.imshow(‘d’,blackhat)
cv2.waitKey(0)
cv2.destroyAllWindows()
梯度运算
梯度在图像处理中常用来衡量像素灰度值变化剧烈程度(如边缘检测)
对于二元函数f(x,y),在图像中x,y为像素坐标,f为灰度值
梯度值超过阈值区域被判定为边缘,因为边缘处灰度变化剧烈,梯度模值大
梯度=膨胀-腐蚀
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\tup.jpg")
ker=np.ones((7,7),np.uint8)
dit=cv2.dilate(img,ker,iterations=5)
ero=cv2.erode(img,ker,iterations=5)
res=np.hstack((dit,ero))
cv2.imshow(‘d’,res)
cv2.waitKey(0)
cv2.destroyAllWindows()
第四章图像梯度计算
Sobel算子
Sobel算子用于图像边缘检测的离散微分算子,核心通过计算图像像素灰度值在水平和垂直方向的梯度来识别灰度变化剧烈的区域(边缘)
cv2.Sobel(src.ddepth,dx,dy,ksize)
ddepth:图像的深度
dx:水平方向
dy:竖直方向
ksize是Sobel算子的大小
#示例
import cv2
import numpy as np
import matplotlib
from matplotlib.pyplot import imshow
#创建cv2模块
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img=cv2.imread(r"C:\Users\19022\Desktop\tds.jpg")
#求x梯度的区域
sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx=cv2.convertScaleAbs(sobelx)#取绝对值
白到黑为正数,黑到白为负数,所有的负数都会被截断成0,所有要取绝对值
【cv2.CV_64F:用与存储图像像素值或计算过程中的中间数据】
#求y梯度的区域
sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely=cv2.convertScaleAbs(sobely)#取绝对值
#求x、y梯度区域
sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(‘dd’,sobelxy)
【直接将x、y设为1,整体效果不好,一般分开计算,最后求和】
Schar算子
scharx=cv2.Scharr(img,cv2.CV_64F,1,0,3)
scharx=cv2.convertScaleAbs(sobelx)
schary=cv2.Scharr(img,cv2.CV_64F,0,1,3)
schary=cv2.convertScaleAbs(sobely)
scharxy=cv2.addWeighted(scharx,0.5,schary,0.5,0)
lapkacian算子
laplacian=cv2.Laplacian(img,cv2.CV_64F)
laplacian=cv2.convertScaleAbs(laplacian)
比较
#示例
import cv2
import numpy as np
import matplotlib
from matplotlib.pyplot import imshow
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")
#sobelx算子
sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx=cv2.convertScaleAbs(sobelx)
sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely=cv2.convertScaleAbs(sobely)
sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
#scharx算子
scharx=cv2.Scharr(img,cv2.CV_64F,1,0,3)
scharx=cv2.convertScaleAbs(sobelx)
schary=cv2.Scharr(img,cv2.CV_64F,0,1,3)
schary=cv2.convertScaleAbs(sobely)
scharxy=cv2.addWeighted(scharx,0.5,schary,0.5,0)
#Laplacian算子
laplacian=cv2.Laplacian(img,cv2.CV_64F)
laplacian=cv2.convertScaleAbs(laplacian)
res=np.hstack((sobelxy,scharxy,laplacian))
cv_show(‘dd’,res)
第五章边缘检测
Canny边缘检测
使用高斯滤波器,以平滑图像,滤波噪声
计算图像中每个像素点的梯度强度和方向
应用非极大值抑制,以消除边缘检测带来的杂散响应
应用双阈值检测来确定真实的和潜在的边缘
通过抑制孤立的弱边缘最终完成边缘检测
#示例
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")
#边缘检测
v1=cv2.Canny(img,80,150)
#指定的越小则检测的越丰富,指定的越大检测的内容越简
v2=cv2.Canny(img,50,100)
res=np.hstack((v1,v2))
cv_show(‘dd’,res)
第六章图像金字塔与轮廓检测
轮廓检测
cv2.findCountours(img,mode,method)
mode:轮廓检索模式
RETR_EXTERNAL:只检索最外面轮廓
RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中
RETR_CCOMP:检索所有的轮廓,并将他们组织为两层;顶层是各部分的外部边界,第二层是空洞的边界
RETR_TREE:检索所有的轮廓,并重构嵌套的整个层次
method:轮廓逼近方法
CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)
CHSIN_SPPROX_SIMPLE:压缩水平的、垂直的和斜的部分,函数只保留他们的终点位置
为提高轮廓检测的准确性,使用二值图像
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")
#获取灰度图像
gray=cv2.cvtColor(img,cv2.COLOR_BGRA2GRAY)
#通过阈值获取二值图像
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
#ret表示阈值,thresh经过阈值处理后的二值数组
cv2.imshow(‘dd’,thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")
#获取轮廓
gray=cv2.cvtColor(img,cv2.COLOR_BGRA2GRAY)
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
#cv2.THRESH_BINARY:大与阈值设为最大值,小于阈值设为最小值
contours,hierachy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#返回轮廓列表,层次结构
#contours:轮廓,hierarchy:层次结构,嵌套关系
#如框子里装有苹果,hierarchy会记录这个层次关系,但图片看到的是平面
#绘制轮廓
draw_img=img.copy()#深拷贝
res=cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
#-1表示绘制所有轮廓,传入具体数字表示绘制对应索引的单个轮廓
#轮廓颜色(0,0,255),线宽2
cv2.imshow(‘dd’,res)
cv2.waitKey(0)
cv2.destroyAllWindows()
轮廓特征
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")
#获取轮廓
gray=cv2.cvtColor(img,cv2.COLOR_BGRA2GRAY)
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hierarch=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#轮廓特征
cnt=contours[0]
#面积
print(cv2.convertScaleAbs(cnt))
#周长,True表示闭合
print(cv2.arcLength(cnt,True))
轮廓近似
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\tup.jpg")
#获取轮廓
gray=cv2.cvtColor(img,cv2.COLOR_BGRA2GRAY)
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hierarch=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#选取轮廓
for cnt in contours:
#获取精度参数
epsilon=0.1*cv2.arcLength(cnt,True)
#epsilon表示精度参数,epsilon越大则轮廓越简化,越小则轮廓越接近原轮廓
#0.1是精度系数
#获取近似后的图像坐标集合
approx=cv2.approxPolyDP(cnt,epsilon,True)
#绘制轮廓
draw_img=img.copy()
res=cv2.drawContours(draw_img,[approx],-1,(0,0,255),2)
#输出图像
cv2.imshow(‘dd’,res)
cv2.waitKey(0)
cv2.destroyAllWindows()
模板匹配
模板从原图像上开始滑动,计算模板与图像被模板覆盖的地方的差别程度,然后将每次计算的结果放入一个矩阵里,作为结果输出。
(加入原图像是AB大小,而模板是ab大小,则输出结果的矩阵是(A-a+a)*(B-b+1))
#示例
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")
#读取模板
template=cv2.imread(r"C:\Users\19022\Desktop\person1.jpg")
#模板框
h,w=template.shape[:2]
#匹配方法
methods=[‘cv2.TM_CCOEFF’,‘cv2.TM_CCORR_NORMED’,‘cv2.TM_CCORR’,‘cv2.TM_CCOEFF_NORMED’,‘cv2.TM_SQDIFF_NORMED’]
#匹配
for meth in methods:
img2=img.copy()
#方法变为可执行
method = eval(meth)
#获取匹配结果分数表
res = cv2.matchTemplate(img, template, method)
#得最大最小值及位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
#根据不同匹配方法获取最相似区域
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
# 画矩形
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(img2, top_left, bottom_right, 255, 2)
#输出图像
plt.subplot(121), plt.imshow(template, cmap=‘gray’)
plt.subplot(122), plt.imshow(img2, cmap=‘gray’)
plt.show()
匹配多个对象
#示例
img_rgb = cv2.imread(r"C:\Users\19022\Desktop\person.jpg")
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread(r"C:\Users\19022\Desktop\person1.jpg", 0)
h, w = template.shape[:2]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
取匹配程度大于等于80的坐标
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]): # *号表示可选参数
bottom_right = (pt[0] + w, pt[1] + h)
cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv2.imshow(‘img_rgb’, img_rgb)
cv2.waitKey(0)
cv2.imshow(‘dd’,res)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像金字塔
高斯金字塔:
向下采样方法(缩小)
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")
print(img.shape)
#向下采用方法
down=cv2.pyrDown(img)
cv2.imshow(‘dd’,down)
print(down.shape)
cv2.waitKey(0)
cv2.destroyAllWindows()
向上采用方法(放大)
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")
print(img.shape)
#向上采样方法
up=cv2.pyrUp(img)
cv2.imshow(‘dd’,up)
print(up.shape)
cv2.waitKey(0)
cv2.destroyAllWindows()
拉普拉斯金字塔:
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\person.jpg")
#缩小
down=cv2.pyrDown(img)
#放大
down_up=cv2.pyrUp(down)
#原减down_up
l_1=img-down_up
cv2.imshow(‘dd’,l_1)
cv2.waitKey(0)
cv2.destroyAllWindows()
第七章直方图与傅里叶变换
cv2.calaHist ,plt.subplot ,plt.plot ,plt.hist ,np.zeros ,cv2.equalizeHist()…
直方图定义
直方图是对图像像素灰度值分布情况的统计可视化工具,以像素值为横轴,对应像素值出现的频次为纵轴
cv2.calcHist是计算图像直方图的核心函数,能直接统计单通道/多通道图像像素值分布情况,输出像素频次的多维数组
使用matplotlip将数组信息转化为可视直方图
cv2.calcHist(images,channels,mask,histSize,ranges)
images:输入图像,格式为unit8或float32,应用中括号[]括起来
channels:计算哪个通过的直方图【灰度图-1个通道,填0】
mask:掩码图像
【为None是计算整幅图的直方图,为掩码图时仅统计‘非0区域’的像素】
histSize:像素值区间数量
【填256则将0-255像素值非为256个区间,填16则将0-255分为16个区间】
ranges:统计像素值范围,常为[0,255]
hist的输出结果是numpy.ndarray数组,维度有channels决定
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\cat.jpg")
#获取像素值频次数组
hist=cv2.calcHist([img],[0],None,[256],[0,255])
#将数组转化为可视化直方图
plt.plot(hist)
#把每一行的唯一元素是=看作y轴,把数组的索引看作x轴
#hist.ravel()将hist的二维数组展平为一维数组
#plt.hist(hist.ravel(),256)无法达到预期
#横纵坐标的含义
plt.xlabel(‘Pixel Value(0-255)’)
plt.ylabel(‘Pixel Count’)
plt.show()
三通道的直方图
#示例
img=cv2.imread(r"C:\Users\19022\Desktop\cat.jpg")
color=(‘b’,‘g’,‘r’)
for i,col in enumerate(color):
histr=cv2.calcHist([img],[i],None,[256],[0,256])
plt.plot(histr,color=col)
plt.xlim([0,256])
plt.show()
掩码mask
plt.subplot:用于在一个窗口中创建子图网络,从而可以在同一个画布上绘制多个独立的图表,实现多图布局展示
plt.psubplot(nrows,ncols,index)
nrows:行数 ncols表示列数 index表示位置
#读取图像
img1=cv2.imread(r"C:\Users\19022\Desktop\cat.jpg",cv2.IMREAD_GRAYSCALE)
img=cv2.pyrDown(img1)
cv2.imshow(‘mask’,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
创建mask
mask = np.zeros(img.shape[:2], np.uint8)
#掩码是二维,忽略颜色通道,[:2]切片操作,只获得前2个通道
mask[100:300, 100:400] = 255
#行100-300,宽100-400区域颜色为白色
cv2.imshow(‘mask’,mask)
cv2.waitKey(0)
cv2.destroyAllWindows()
#截取
masked_img = cv2.bitwise_and(img, img, mask=mask) # 与操作
cv2.imshow(‘masked_img’,masked_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#图像直方图
hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])#全部
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])#掩码
plt.subplot(221), plt.imshow(img, ‘gray’)
plt.subplot(222), plt.imshow(mask, ‘gray’)
plt.subplot(223), plt.imshow(masked_img, ‘gray’)
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0, 256])
plt.show()
均衡化
plt.plot():用于绘制线图,可通过参数调整绘制散点图,标记点等
cv2.equalizeHist():对输入的灰度图进行均衡化操作
plt.hist():用于绘制直方图
np.hstack():用于在水平方向上堆叠数组
np.hstack(tup)中tup是一个元组/列表/其他可迭代对象
用于图像的拼接或组合,灵活处理或展示图像或相关图像数据
####整体均衡化
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\cat.jpg",cv2.IMREAD_GRAYSCALE)
plt.hist(img.ravel(),256)
plt.show()
#均衡化
equ=cv2.equalizeHist(img)
plt.hist(equ.ravel(),256)
plt.show()
#展示均衡化之后的图像
res=np.hstack((img,equ))
res1=cv2.pyrDown(res)
cv2.imshow(‘dd’,res1)
cv2.waitKey(0)
cv2.destroyAllWindows()
####分格均衡化
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\cat.jpg",cv2.IMREAD_GRAYSCALE)
plt.hist(img.ravel(),256)
plt.show()
#均衡化
equ=cv2.equalizeHist(img)
plt.hist(equ.ravel(),256)
plt.show()
clahe=cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
res_clahe=clahe.apply(img)
res=np.hstack((img,equ,res_clahe))
res1=cv2.pyrDown(res)
res2=cv2.pyrDown(res1)
cv2.imshow(‘dd’,res2)
cv2.waitKey(0)
cv2.destroyAllWindows()
傅里叶概述
float32(32为浮点数):可以表示小数,精确表示像素值在一个很大范围内连续的变化,如傅里叶
uint8(8位无符号整数):取值为0-255,是图像存储中最常用的数据类型
高频:变化剧烈的灰度分量,例如边界
低频:变化缓慢的灰度分量,例如一片大海
低通滤波器:只保留低频,会使得图像变模糊
高通滤波器:只保留高频,会使得图像细节增强
cv2.dft():离散傅里叶变换核心函数,实现图像从空间域到频域的转换
输入图像必须是浮点数类型
DFT的结果是复数形式,输出为(H,W,2)形状的数组,最后一位0为实部,1为虚部
输出结果需进行移动,使用np.fft.fftshift移到中心
cv2.idft():离散傅里叶逆变换的核心函数,实现先将频域处理后的复数数组还原到空间域(即我们平时直观看到的图像)
输入cv2.dft()的复数数组
逆变换仍为复数数组,需通过cv2.magnitude计算幅度,得到图像
对灰度图进行离散傅里叶变换(DFT)
#示例
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\cat.jpg",cv2.IMREAD_GRAYSCALE)
#转换图像格式,转换成浮点数
img_float32=np.float32(img)
#进行傅里叶变换
dft=cv2.dft(img_float32,flags=cv2.DFT_COMPLEX_OUTPUT)
#flags=cv2.DFT_COMPLEX_OUTPUT表示输出结果为复数
dft_shift=np.fft.fftshift(dft)
#np.fft.fftshift():对dft进行中心化操作,将低频成分移到中心位置
傅里叶变换结果中,低频成分集中在频谱角落,高频成分分布在边缘,移到中心可以让频谱更直观
#计算幅度谱
magnitude_spectrum=20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
#傅里叶变换的幅度值动态范围过大,不利观察,进行对数变换np.log
#cv2.magnitud():计算复数的幅度
#dft_shift[:,:,0]:是傅里叶变换结果的是实部
#dft_shift[:,:,1]:是傅里叶变换结果的是虚部
#显示图像
plt.subplot(121),plt.imshow(img,cmap=‘gray’)
plt.title(‘Input Image’),plt.xticks([]),plt.yticks([])
#plt.subplot():创建子图
plt.subplot(122),plt.imshow(magnitude_spectrum,cmap=‘gray’)
plt.title(‘Magnitudre Spertrum’),plt.xticks([]),plt.yticks([])
plt.show()
低通滤波器
#示例
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\cat.jpg",cv2.IMREAD_GRAYSCALE)
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, ccol = int(rows/2), int(cols/2)
#频谱中心位置
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
#将频谱60*60的范围设为1,区域区域设为0
逆傅里叶图像还原
fshift = dft_shift * mask
#保留低频,去除高频
f_ishift = np.fft.ifftshift(fshift)
#移回原位置
img_back = cv2.idft(f_ishift)
#得到复数图像
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])
#得到像素图像
#画布显示
plt.subplot(121), plt.imshow(img, cmap=‘gray’)
plt.title(‘Input Image’), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img_back, cmap=‘gray’)
plt.title(‘Result’), plt.xticks([]), plt.yticks([])
plt.show()
高通滤波器
#示例
#读取图像
img=cv2.imread(r"C:\Users\19022\Desktop\cat.jpg",cv2.IMREAD_GRAYSCALE)
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, ccol = int(rows/2), int(cols/2) # 中心位置
高通滤波
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 0
IDFT
fshift = dft_shift * mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])
plt.subplot(121), plt.imshow(img, cmap=‘gray’)
plt.title(‘Input Image’), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img_back, cmap=‘gray’)
plt.title(‘Result’), plt.xticks([]), plt.yticks([])
plt.show()
第八章图像特征-harris
角点检测
cv2.cormerHarris()
img:数据类型为float32的人图像
blockSize:角点检测中指定区域的大小
ksize:Sobel求导中使用的窗口大小
k:取值参数为[0,04,0.06]
#示例
img1= cv2.imread(r"C:\Users\19022\Desktop\cat.jpg")
img=cv2.pyrDown(img1)
print(‘img.shape:’, img.shape)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
print(‘dst.shape:’, dst.shape)
img[dst>0.01*dst.max()] = [0, 0, 255]
cv2.imshow(‘dst’, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
更多推荐
所有评论(0)