本节内容上接这篇博客:
- Opencv-图像操作与处理入门基本知识(一)
笔记来源
- (全)基于python的Opencv项目实战
- 黑马程序员人工智能教程_10小时学会图像处理OpenCV入门教程
理解阈值是干什么的?
假如有如图上的像素点数值,对于每一个像素点值进行判断:该像素点大于阈值如何处理,小于阈值如何处理
这就是阈值函数要做的事情
平滑处理:即滤波操作
normalize = True :会做归一化,即进行核大小的计算,再除去核大小
距离越近越重视,发挥的效果越好;越远发挥的效果不是那么好
中值
:从小到大排序,找到中间的数值
这条线左右两边都是白色一样,这条线不会产生梯度,因此边缘会产生梯度
这个点左边是0(黑)右边是255(白),左右两边梯度大一些 类似边缘检测
算法简单,实际应用效率高于canny边缘检测效率,但是准确度是低于canny的
Sobel算子是高斯平滑与微分操作的结合体:
抗噪声能力强
,适用于效率要求较高,细纹处理要求不高的时候
考虑水平(Gx)和竖直(Gy)两个方向
右减左,下减上
将sobel算子的部分中ksize设为-1,就是利用Scharr进行边缘检测
此处建议分开计算Sobelx,Sobely,再计算整体
使结果差异更明显(数值更大)
中文名称:拉普拉斯算子
对噪音点敏感,可能并不是好事,因为一些噪音点并不是一些边界
边缘检测原理是图像处理和计算机视觉中的基本问题,边缘检测的目标是
标识数字图像中亮度变化明显的点
。
图像中属性中的显著变化通常反应了属性的重要事件和变化。
图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关地信息,保留了图像重要地结构属性。
常用的边缘检测方法可以分为两类:
- 基于搜索
- 基于零穿越
被认为是
最优的边缘检测算法
高斯滤波器:中间点比较大,边缘比较小
使用的Sobel算子
具体看图像梯度中的Sobel算子
minval取值较小:希望检测的边界尽可能多,但是结果可能是不是边界的也认为成边界;minval取值较大,要求高,只有极为边界的时候才有可能拿出来
综上两幅图像,
阈值大小的设定要自己进行测试,并不是越大或者越小合适
canny = cv2.Canny(image,threshold1,threshold2)
参数:
- image:灰度图
- threshold1:minval较小的阈值将间断的边缘连接起来
- threshold2:maxval较大的阈值检测图像中明显的边缘
import cv2 as cv
import numpy as np
path = 图片路径
img = cv.imread(path)
# 边缘检测
lowThreshold = 0 # minval
max_lowThreshold = 100 #maxval
canny = cv.Canny(img,lowThreshold,max_lowThreshold )
# 图像显示
...
先前边缘检测的部分是零零散散的线段,不能称之为轮廓。
轮廓应该是整体,连接在一起的是轮廓。
为了更高的准确率,使用二值图像
- 读取数据
- 转换为灰度图
- 图像阈值处理(对图像数据进行二值处理)
- 调用轮廓检测函数
保存的是
轮廓信息
直接使用cv.inread()读取的原图想绘制轮廓
该方法中的参数 -1自己测试即可
注意此时再进行原图像展示:
因此,需要复制img,
img_ = img.copy()
可以进行图片中每一个轮廓的面积
将曲线可以近似成直线,类似将一条曲线不断地近似成直线,如果一条直线不可以,则两条、三条、直到可以。。
直方图是对数据进行统计的一种方法,并且将统计值组织到一系列实现定义好的bin当中.其中,bin为直方图中经常用到的一个概念,可以译为“直条”或“组距",其致值是从数据中计算出的特征统计量,这些数据可以是诸如梯度、方向、色彩或任何其他特征。
图像直方图(Image Histogram)是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素个数。
这种直方图中,横坐标的左侧为较暗的区域,而右侧为较亮的区域。因此一张较暗图片的直方图中的数据多集中于左侧和中间部分,而整体明亮、只有少量阴影的图像则相反。
注意:
直方图是根据灰度图进行绘制的
,而不是彩色图像。假设有一张图像的信息(灰度值0-255,已知数字的范围包含256个值,于是可以按一定规律将这个范围分割成子区域(也就是bins)
[0, 255) = [0, 15] U ]16, 30] …U [240, 255]
- dims:需要统计的特征数目。在上例中,dims =1,因为仅仅统计了灰度值;要统计RGB三色的即dims = 3
- bins:每个特征空间子区段的数目,可译为“直条"或“组距”,在上例中,bins = 16.
- range:要统计特征的取值范围。在上例中,range =[0,255].
- 直方图是图像中像素强度分布的图形表达方式。
- 它统计了每一个强度值所具有的像素个数
- 不同的图像的直方图可能是相同的
cv2.calcHist(images,channels,mask,histSize,ranges[,hist[,accumualte]])
# 创建掩膜
mask = np.zeros(img.shape[:2],np.unit8)
mask[400:650,200,500] = 1
plt.imshow(mask,cmap=plt.cm.gray)
mask_img = cv.bitwize_and(img,img,mask=maks) # 与操作
plt.imshow(mask_img ,cmap=plt.cm.gray)
mask_hist = cv.calcHist([img],[0],mask,[256],[0,256])
plt.plot(mask_hist) # 折线图
plt.show()
img.shape[:2] 表示取彩色图片的长、宽。
img.shape[:3] 则表示取彩色图片的长、宽、通道。
关于img.shape[0]、[1]、[2]
img.shape[0]:图像的垂直尺寸(高度)
img.shape[1]:图像的水平尺寸(宽度)
img.shape[2]:图像的通道数
在矩阵中,[0]就表示行数,[1]则表示列数
import cv2
image=cv2.imread("D:/shape.bmp")
print(image.shape[0])
print(image.shape[1])
print(image.shape[2])
结果
300
200
3
如何获得上述图像?
要保存图像的部分设置为255:mask[100:300,100:400] = 255
dist = cv.equalizeHist(img)
dist = cv.equalizeHist(img)
plt.inshow(dist,cmap=plt.cm.gray) # 均衡化图像
plt.inshow(img,cmap=plt.cm.gray) # 原始图像
有些地方会更亮,有些地方也会变暗(例如猫退或者猫尾)
cv.createCLAHE(clipLimit,tileGridSize)
参数:clipLimit:对比度限制,默认是40
tileGridSize:分块的大小,默认8*8
calhe.apply(img) :
对img进行限制对比度自适应直方图均衡化
我们生活在时间的世界中,早上7:00起来吃早饭,8:00去挤地铁,9:00开始上班…以时间为参照就是
时域分析
。
但是在频域中一切都是静止的
!
傅里叶分析之掐死教程
- 高频:变化刚烈的灰度分量,例如边界(变化剧烈的是高频)
- 低频:变化缓慢的灰度分量,例如一片大海(变换缓慢的是低频)
- 低通滤波器:只保留低频,会使得图像模糊
- 高通滤波器:只保留高频,会使得图像细节增强
- opencv中主要就是
cv2.dft()
(和cv2.idft()
-逆变换),输入图像需要先转换成np.fioat32格式- 得到的结果中频率为0的部分会在左上角,通常要转换到中心位置,可以通过
shift变换
来实现.- cv2.dt()返回的结果是双通道的(实部,虚部),通常还需要转换成
图像格式
才能展示(0,255)
高通滤波器只保留了一些边界信息,没有留下一些细节信息
至此为止,我仍未理解傅里叶变换,若有通俗易懂的教程,欢迎留言,万分感谢
方向:
从左到右,从上到小
模板匹配
:在给定的图片中查找和模板最相似的区域,该算法的输入包括模板和图片,整个任务的思路就是按照滑窗
的思路不断地移动模板图片,计算其与图像中对应区域的匹配度
【与机器学习中的相似度概念类似】,最终将匹配度最高地区域选为最终的结果。
- 准备两幅图像
- 原图像:在这幅图中,找到与模板匹配的区域
- 模板:与原图像进行对比的图像块
res = cv.matchTemplate(img,tempate,method)
参数:
img :进行模板匹配的图像
Template :模板
method:实现模板匹配的算法:
import cv2 as cv
import numpy as np
path_ori = 原图像路径
path_com = 模板图像路径
img = cv.imread(path_ori )
template = cv.imreda(path_com )
h,w,l = template.shape
# 模板匹配
res = cv.matchTemplate(img,template,cv.TM_CCORR) # 使用相关系数匹配 得到结果矩阵
# 返回图像中最匹配的位置 确定左上角的坐标,并将匹配位置绘制在图像上
min_val,max_val,min_loc,max_loc = cv.minMaxLoc(res)# 最小值 最大值 最小位置 最大位置
top_left = max_loc # 最大位置是最好的位置 top_left 左上角位置
bottom_right = (top_left[0]+w,top_left[1]+h) # 右下角位置
cv.rectangle(img,top_left,bottom_right ,(0,255,0),2)
# 显示图像
plt.imshow(img[:,:,::-1])
plt.show()
模板匹配不适用于尺度变换,视角变换后的图像,这时我们就要使用关键点匹配算法,比较经典的关键点检测算法包括SIFT和SURF等,主要的思路是首先通过关键点检测算法获取模板和测试图片中的关键点;然后使用关键点匹配算法处理即可,这壁关键点可以很好的处理尺度变化、视角变换、旋转变化、光照变化等,具有很好的不变性。
霍夫变化
常用来提取图像中的直线和圆等几何形状
假设有100*100的图片,使用霍夫变换检测图片中的线,步骤如下:
cv2.HoughLines(img,rho,theta,threshold)
参数:
- img:
二值化
推向或者进行Canny边缘检测
- rho、theta:ρ和θ的精确度
- threshold:阈值,只有累加器中的值高于该值时才被认为是直线
import numpy as np
import random
import cv2 as cv
# 转换为二值图
path = 图片路径
img = cv.imread(path)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edged = cv.Canny(gray,50,150)
# 霍夫直线变换
lines = cv.HoughLines(edges,0.8,np.pi/100,150) # 返回检测到的所有直线
# 绘制图像 极坐标 -》 笛卡尔
for line in lines:
rho,theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0+1000(-b))
y1 = int(y0+1000(a))
x2 = int(x0-1000(-b))
y2 = int(y0-1000(a))
cv.line(img,(x1,y1),(x2,y2),(0,255,0)) # 绿色线
注意:霍夫圆检测对噪声比较敏感,首先应该进行中值滤波
import cv2 as cv
import numpy as np
path = 图片路径
img = cv.imread(path)
gry_img = cv.cvtColor(planets,cv.COLOR2GRAY)
# 中值滤波 去除噪点
img = cv.medianBlur(gay_img,7)
# 霍夫圆检测
circles = cv.HoughCircles(img,cv.HOUGH_GRADIENT,1,200,PARAM1=100,PARAM2=30,minRadius=0 ,minRadius=100 )
# 绘制结果
for i in ciecles[0,:]:
# 绘制圆形
cv.circle(planets,(i[0],i[1]),i[2],(0,255,0),2)
# 绘制圆心
cv.circle(planets,(i[0],i[1]),2,(0,255,0),3)
这篇博客是结合两个视频所记下来的,难免有些差错或者个人误解,希望大家能够指出错误,一起进步!