在线网站排名工具,巩义网站建设哪家专业,wordpress本地,赣州信息港人才频道计算机视觉#xff08;OpenCVTensorFlow#xff09; 文章目录 计算机视觉#xff08;OpenCVTensorFlow#xff09;前言3.图像金字塔3.1 高斯金字塔3.2 拉普拉斯金字塔 4.图像轮廓图像边缘和图像轮廓的区别检测图像绘制边缘 5.轮廓近似外接矩形外接圆 6. 模板匹配6.1 什么是…计算机视觉OpenCVTensorFlow 文章目录 计算机视觉OpenCVTensorFlow前言3.图像金字塔3.1 高斯金字塔3.2 拉普拉斯金字塔 4.图像轮廓图像边缘和图像轮廓的区别检测图像绘制边缘 5.轮廓近似外接矩形外接圆 6. 模板匹配6.1 什么是模板匹配 总结 前言
本系列文章是OpenCV系列文章的第三篇仍然跟随上篇内容主要聚焦于图像的一些操作 3.图像金字塔 在通常情况下我们使用大小恒定的图像。但在某些情况下我们需要使用不同分辨率的同幅图像例如在搜索图像中的某些内容比如脸部信息时并不确定该内容在图像中占据的大小。这种情况下我们需要创建一组不同的分辨率的相同图像并在所有图像中搜索该内容。这些不同分辨率的图像被称为图像金字塔因为当它们堆叠排列时底部为最高分辨率图像而顶部为最低分辨率图像看起来像金字塔 **图像金字塔主要有两种**高斯金字塔拉普拉斯金字塔
3.1 高斯金字塔
向上采样在图像金字塔中越靠下的分辨率越大所以向上采样指的是从分辨率大的图像中得到分辨率小的图像方法
将图像与下方的高斯核进行卷积就是我们前几次一直说的对应位置相乘最后都加在一起从而代替中间像素的那个值将所有偶数行和偶数列去除。
为什么要先卷积再去除呢是因为如果直接去除偶数行和偶数列那势必会导致大量数据的丢失如果我们先卷积卷积后的值是它周围的值共同作用的所以卷积后再去除损失的数据量比直接去除要小很多但是还是会少一部分数据向下采样在图像金字塔中越靠上的分辨率越大所以向下采样指的是从分辨率小的图像中得到分辨率大的图像**方法 **我们看第一步放大后有近四分之三的数据都是0第二部卷积后实际上是把不是0的数据给分配了一部分给0那实际上就是把原有的数据给往四周分散了。那在放大的时候原来的数据给了其他的那对应自身来说不也就是丢失了一部分数据。
# 引入图片
imgcv2.imread(AM.png)
cv_show(img,img)
print (img.shape)
# 向上采样
upcv2.pyrUp(img)
cv_show(up,up)
print (up.shape)
# 向下采样
downcv2.pyrDown(img)
cv_show(down,down)
print (down.shape)**而为了让数据尽量的少丢失点我们又有了拉普拉斯金字塔。 **
3.2 拉普拉斯金字塔
https://blog.csdn.net/ftimes/article/details/106731558 ** 在高斯金字塔中我们提到了上采样和下采样。但是无论是上采样还是下采样都会丢失像素值所以这两种操作并不是可逆的。也就是说对一幅图先进行上采样再进行下采样是无法恢复到原始状态。同样先下采样再上采用也无法恢复到原始状态** 因此我们引入了拉普拉斯金字塔The Laplacian pramid简而言之拉普拉斯金字塔的第 i 层是由【高斯金字塔的第 i 层】 与 【高斯金字塔中的第 i1 层的向上采样结果】之差。简单来说拉普拉斯金字塔是一个 高斯差值金字塔下面这个图就是一个拉普拉斯每一层的流程下面这个图简化了上图的流程我们从后往前看G3向上取样后G2减去它就是 L2。而 G3加上L2就是G2。因为L2G2-G3向上
upcv2.pyrUp(img)
up_downcv2.pyrDown(up)
cv_show(img-up_down,img-up_down)4.图像轮廓 图像边缘和图像轮廓的区别 ** 前面我们在图像形态学操作里用cv2.morphologyEx()这个函数实现图像梯度的提取用膨胀图像-腐蚀图像获取一个图像中前景图像的边缘。还有我们的礼帽和黑帽一定程度也能提取图像的边缘信息。依旧我们在图像梯度中详细讲过的 sobel算子scharr算子laplasian算子canny边缘检测这些都是检测图像中边缘线条的。** ** 而本章讲的是图像轮廓图像轮廓和图像边缘不少一回事图像边缘不少图像轮廓图像边缘是图像中的线条这些线条是不连续的零散的线段只要是由梯度把由梯度的像素点提取出来就可以了这是边缘检测的操作手法。而图像轮廓首先要是一个整体的就是将边缘连接起来形成一个整体这才叫轮廓。** ** 边缘检测主要是通过一些手段检测数字图像中明暗变化剧烈即梯度变化比较大像素点偏向于图像中像素点的变化。如Canny边缘检测结果通常保存在和原图片一样尺寸和类型的边缘图中。轮廓检测指检测图像中的对象边距更偏向于关注上层语义对象主要用来分析物体的形态比如物体的周长和面积等。可以说 边缘包括轮廓。** ** 边缘主要是作为图像的特征使用比如可以用边缘特征可以区分脸和手而轮廓则是一个很好的图像目标的外部特征这种特征对于我们进行图像分析目标识别和理解等更深层次的处理都有很重要的意义** 检测图像
在OpenCV中我们用 image, contours, hierarchy **cv2.findContours(img,mode,method) **这个函数来得到轮廓
img要做轮廓检测的图像必须是8位单通道二值图像。所以一般情况下我们都是将图像处理位二值图像后再将其作为参数传入。在很多情况下我们是预先对图像进行阈值分割或者边缘检测处理比如经过Canny拉普拉斯等边缘检测算子处理过的二值图像在得到满意的二值图像后再作为参数传入使用这样效果会更好。mode轮廓检索模式。均可了轮廓的提取方式 cv2.RETR_EXTERNAL只检测最外面的轮廓cv2.RETR_LIST减少所有的轮廓并将其保存到一条链表当中对检测到的轮廓不建立等级关系cv2.RETR_CCOMP检索所有轮廓并将它们组织成两级层次结构。顶层是各部分的外部边界第二层是空洞的边界。cv2.RETR_TREE检索所有轮廓并建立一个等级树结构的轮廓就是重构嵌套轮廓的整个层次说明一般情况下我们只用第4种模式因为第4种模式是检测所有的轮廓并且把这些轮廓按层次保存成一个树结构后面如果我们有需要直接调用即可。 method轮廓逼近方法就是如何表达轮廓意思就是我是用线表示轮廓呢还是简单的用2个点就表示一条线的轮廓 cv2.CHAIN_APPROX_NONE以 Freeman 链码的方式输出轮廓意思就是我存储了所有的轮廓点就是相连两个点的像素位置差不超过 1 我可以用完整的线条来表示轮廓就是我可以画出一个完整的轮廓。cv2.CHAIN_APPROX_SIMPLE压缩水平方向垂直方向对角线方向的元素只保留该方向的终点坐标。比如一个矩形只用4个点就可以表示。同理如果是一个多边形我们就输出这个多边形的订单序列
函数返回值
image与参数img的尺寸一致的。后面高版本的opencv已经不返回这个对象contours是返回的轮廓。这个轮廓是一个数组hierachy是轮廓的层次信息就是mode参数决定的返回的轮廓数据的组织结构说明在opencv中我们都是从黑色背景种查找白色对象因此对象必须是白色的背景必须是黑色的
使用轮廓检测函数 cv2.findContours()要注意的点
我们检测一张彩图的轮廓是首先我们要把彩图转换为灰度图像然后我们用阈值函数把灰度图像处理成二值图像此时才能作为参数 img 传入到函数中我们检测轮廓的时候一张图片可能有多个轮廓也可能有一个轮廓礼貌套几个轮廓就是空洞所以我们要明确我们想要检测几级轮廓。 当我们只想检测最外面的一层轮廓时参数 modecv2.RETR_EXTERNAL当我们像检测所有的轮廓就是轮廓里面套轮廓可以嵌套多层时参数mode可以选择其他三种 cv2.RETR_LIST是把所用的轮廓放到一起不区分轮廓之间的等级关系cv2.RETR_CCOMP是把所有的轮廓分2级cv2.RETR_TREE是建立一个树结构的层次关系 当我们轮廓检测完毕后不管是检测一个轮廓还是检测所有的轮廓检测所有轮廓不管是保存轮廓之间的等级关系还是不保存我们的轮廓本身数据可以有两种方式存储、 cv2.CHAIN_APPROX_NONE就是保存轮廓的所有像素点此时返回的 contours可视化处理后就是轮廓线。cv2.CHAIN_APPROX_SIMPLE就是表示我们轮廓数据不是连续的像素点而是轮廓的顶点序列此时我们可视化 contours时就是一些顶点就是轮廓的顶点不是线。countours的属性 len(contours)返回的就是我们检测到了几个轮廓len(contours[i])返回第 i 个轮廓长度就是它有多少个像素点contours[i].shape返回的就是轮廓内点的形状比如412就表示轮廓 i 有4个轮廓点每个点是1行两列[[79,270]] [[79,383]]** [[195,383]]** [[195, 270]] 这其实就是一个方框轮廓的4个点的坐标值。** hierarchy是我们检测到的轮廓的等级关系的数据这个数据可以反映我们的轮廓之间是如何连接的。
绘制边缘
轮廓绘制函数cv2.drawContours(img, contours, contourIdx, color [ thickness, lineType, hierarchy, maxLevel, offset] )
img待绘制轮廓的图像contours需要绘制的轮廓这个参数就是 findContours()的输出contourldx需要绘制的轮廓的索引号如果 contourldx-1,表示绘制全部轮廓如果这个参数是零或者正整数表示要绘制的轮廓是对应的索引号的轮廓color绘制的颜色用 BGR 表示thickness表示轮廓的粗细如果 thickness-1则表示要绘制实心轮廓lineType轮廓的线条形状hierarchycv2.findContours()返回的层次信息。maxLevel要绘制的轮廓的偏移到不同的位置展示出来
注意由于该函数是在 img 的基础上绘制的不会再重新生成一个带轮廓的新对象所有这个函数是在原图中绘制的。所以我们要保存原图轮廓检测步骤小结
当我们拿到的原图是一张彩色图的时候第一步我们要把彩色图变成灰度图把灰度图用阈值函数处理成二值图像检测轮廓绘制轮廓
# 导入图片
img cv2.imread(contours.png)
# 彩色图转灰色图
gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 灰色图转二值图
ret, thresh cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show(thresh,thresh)
# 检测轮廓
binary, contours, hierarchy cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# 画轮廓
draw_img img.copy()
res cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
cv_show(res,res)5.轮廓近似 我们看下面这个图片它不是一个规则的图形是一个不规则的图形如果要精确的描述轮廓的话就是第三幅图 如果像要近似的表示的话就是第二幅图用一个矩形就可以表示 https://blog.csdn.net/SSJJRRRR/article/details/108478898那OpenCV的 approxPolyDP 函数就可以实现这个功能。approxPolyDP函数使用了 Douglas-Peucker算法
先从轮廓中找出两个最远的点将两点相连即 b-c ;在原来的轮廓上查找一个里线段距离最远的点将该点加入逼近后的新轮廓中即 c-d 然后重复前面的算法不断迭代将最远的点添加进来直到所有的点到多边形的最短距离小于指定的精度
在OpenCV中 cv2.approxPolyDP(cnt,epsilon,True) 就是用来得到近似轮廓cnt 就是 findContours函数得到的 contoursepsilon就是精度最后一个布尔值如果为true则闭合近似曲线其第一个和最后一个顶点为连接的否则不闭合。
# 导入图片
img cv2.imread(contours2.png)
# 转成灰度图
gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 转为二值图
ret, thresh cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 检测轮廓
binary, contours, hierarchy cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt contours[0]
# 画出轮廓
draw_img img.copy()
res cv2.drawContours(draw_img, [cnt], -1, (0, 0, 255), 2)
cv_show(res,res)
# arcLength轮廓的周长epsilon是精度
epsilon 0.15*cv2.arcLength(cnt,True)
# 得到近似轮廓
approx cv2.approxPolyDP(cnt,epsilon,True)
# 画出轮廓
draw_img img.copy()
res cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)
cv_show(res,res)外接矩形 x,y,w,hboundingRect(cnt) cnt 就是一个轮廓x,y是矩形的左上角坐标而w,h为矩形的宽度和高度 img cv2.rectangle(img,(x,y),(xw,yh),(0,255,0),2) img画轮廓的图片 (x,y)矩形的左上角的坐标 (xw,yh)矩形的右下角的坐标 (0,255,0)颜色 BGR 2线条宽度 # 引入坐标
img cv2.imread(contours.png)
# 转为灰度图
gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 转为二值图
ret, thresh cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 检测轮廓
binary, contours, hierarchy cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt contours[0]
# 找到外接矩形的信息
x,y,w,h cv2.boundingRect(cnt)
# 画矩形
img cv2.rectangle(img,(x,y),(xw,yh),(0,255,0),2)
cv_show(img,img)外接圆 (x,y),radius cv2.minEnclosingCircle(cnt) cnt就是一个轮廓 (x,y)圆心坐标 radius半径 img cv2.circle(img,center,radius,(0,255,0),2) 参数基本上与外接矩形都差不多 (x,y),radius cv2.minEnclosingCircle(cnt)
center (int(x),int(y))
radius int(radius)
img cv2.circle(img,center,radius,(0,255,0),2)
cv_show(img,img)6. 模板匹配 6.1 什么是模板匹配
https://blog.csdn.net/m0_37579176/article/details/116950903 模板匹配可以看作是对象检测的一种非常基本的形式。使用模板匹配我们可以使用包含要检测对象的”模板“来检测输入图像中的对象。 也就是说我们需要两个图像来应用模板匹配
源图像这是我们希望在其中找到的与模板匹配的图像模板图像我们要搜索的图像
为了在源图像中找到模板图像我们在源图像中从左到右和从上到下依次滑动模板应用模板匹配就像在源图像上从左到右从上到下滑动模板在每一个位置都计算一个指标以表明这个位置处两个图像块之间匹配程度的高低在每个(x,y)位置都会计算一个度量来表示匹配的“好”或“坏”。通常我们使用归一化的相关系数来确定两个图像块之间像素强度有多“相似”相关系数有很多计算方式。‘对于模板 T 在源图像 I 上的每个位置取两者重合部分的图像块计算相似度度量结果存储在结果矩阵 R 中。源图像中的每个xy坐标在结果矩阵 R 中包含一个条目除非模板越界
下图就是结果矩阵与源图像重叠后的图像在这里我们可以可视化叠加在原始图像上的结果矩阵R。注意R与原始模板大小不相同。这是因为整个模板必须在源图像的内部滑动得到等大的两个图像块才能计算相关性。如果模板超出了源的边界我们将不计算相似性度量。结果矩阵中 R 最亮的位置表示最佳匹配位置而暗区表示该点源图像和模板图像之间的相关性很小当模板图像中的水杯与源图像中的水杯两者完全重合的时候模板图像左上角所在的源图像位置存储的是模板与源图像相似的的最大值。但是我们需要确保要检测的模板与源图像中检测的对象几乎完全相同。即使外观很小的偏差也会极大地影响匹配的结果。在OpenCV中我们可以使用 cv2.matchTemplate()进行模板匹配这个函数有三个参数
输入图像包含我们要检测的对象的图像模板图像对象的图像模板匹配方法
- TM_SQDIFF计算平方不同计算出来的值越小越相关 - TM_CCORR计算相关性计算出来的值越大越相关- TM_CCOEFF计算相关系数计算出来的值越大越相关- TM_SQDIFF_NORMED计算归一化平方不同计算出来的值越接近0越相关- TM_CCORR_NORMED计算归一化相关性计算出来的值越接近1越相关- TM_CCOEFF_NORMED计算归一化相关系数计算出来的值越接近1越相关另外值得注意的是如果您只想检测模板图像上的特定区域则可以为模板图像提供一个掩膜如下所示**result cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED, mask) **
掩膜即为模板图像上感兴趣的区域用于忽略模板图像上无用的干扰的特征即不属于检测目标的干扰特征。对于模板上你不希望被搜索的区域掩膜值应该设置为0。对于模板图像上您要进行搜索的区域掩膜值应该设置为255。掩膜与模板图像具有相同的维度并且每个元素的类型也需要一致。
# 引入源图像
img cv2.imread(lena.jpg, 0)
# 引入模板图像
template cv2.imread(face.jpg, 0)
# 模板匹配
res cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
# 得到最大的像素点和最小的像素点的值和坐标
min_val, max_val, min_loc, max_loc cv2.minMaxLoc(res)
# 根据方法选择最大值或最小值的坐标
# 如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED取最小值
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)总结
这次紧接者上篇内容再一次讲解了一些有关图像的操作预计还需要一期把图像操作讲个差不多后进入实战环节将上述图像内容通过实战进行一个强化训练
我是Mayphry从一点点到亿点点我们下次再见