图像梯度
- 一阶导数与Sobel算子
- 二阶导数与拉普拉斯算子二阶导数与拉普拉斯算子
代码层面知识点
- sobel算子
- 拉普拉斯算子
- opencv api应用
1.Sobel算子
首先 x方向梯度 再算y方向梯度
*addWeighted()函数是将两张相同大小,相同类型的图片融合的函数。
API详解:void cvAddWeighted( const CvArr src1, double alpha,const CvArr src2, double beta,double gamma, CvArr dst );
参数1:src1,第一个原数组.
参数2:alpha,第一个数组元素权重
参数3:src2第二个原数组
参数4:beta,第二个数组元素权重
参数5:gamma,图1与图2作和后添加的数值。不要太大,不然图片一片白。总和等于255以上就是纯白色了
Scharr是Sobel的增强版
2.拉普拉斯算子
对图像做卷积
void cv.Filter2D( const CvArr src, CvArr* dst,const CvMat* kernel,CvPoint anchor=cvPoint(-1,-1));
#define cvConvolve2D cvFilter2D*
其中src为输入图像.dst为输出图像.kernel为卷积核, 单通道浮点矩阵. anchor核的锚点表示一个被滤波的点在核内的位置。锚点应该处于核内部。缺省值 (-1,-1) 表示锚点在核中心。
如果想要应用不同的核于不同的通道,先用 cvSplit 函数分解图像到单个色彩通道上,然后单独处理。
Canny边缘提取
canny算法介绍
opencv中演示
canny是边缘检测算法,是一个很好的边缘检测器 很常用也很实用的图像处理方法 对噪声较为敏感
分为五步:
一、首先图像通过高斯去掉噪声 GaussianBlur
均值滤波:其函数声明为:void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )。
这个函数在上一节中介绍过了,这里简单些一下。
功能:对输入的图像src进行均值滤波后用dst输出。
参数:src和dst当然分别是输入图像和输出图像。size为均值滤波器模板大小。Anchor为锚点(具体什么没看源码不懂),如果为Point(-1,-1),则锚点是滤波器的中心点。borderType为边缘点插值类型。
理解:以原图对应像素为中心的与模板中心重叠,将模板覆盖领域内全部像素求均值就是滤波后像素的值了。
高斯滤波:其函数声明为: void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT ) ;
功能:对输入的图像src进行高斯滤波后用dst输出。
参数:src和dst当然分别是输入图像和输出图像。Ksize为高斯滤波器模板大小,sigmaX和sigmaY分别为高斯滤波在横线和竖向的滤波系数(有点晦涩,等下解释)。borderType为边缘点插值类型。
理解:数字图像的滤波可以简单的这么理解,就是对原图像的每一个像素滤波,那么对应这个像素滤波后的值是根据其相邻像素(包括自己那个点)与一个滤波模板进行相乘即可。所以具体到高斯滤波,我们只要知道这个高斯滤波的模板即可。
二.灰度转换 cvtColor
*cvtcolor()*函数是一个颜色空间转换函数,可以实现RGB颜色向HSV,HSI等颜色空间转换。也可以转换为灰度图。
API详解:void cv::cvtColor(cv::InputArray src, // 输入图
cv::OutputArray dst, // 输出图
int code, // 颜色映射类型,可以查表得到,有很多
int dstCn = 0 // 输出的通道数 (0=‘automatic’),我们可以使用默认值,什么都不写。
三.计算梯度、 Sobel/Scharr
src和dst分别是输入图像和输出图像
xorder和yorder是求导的阶数。通常是0,1,最多2。值为0表明在这个方向上没有求导
aperture_size参数是方形滤波器的宽(或高)并且应该是奇数,1,3,5,7
如果源图像src是8位的,为避免溢出,目标图像的深度必须是IPL_DEPTH_16S
Scharr滤波器
对于小一点的核(3x3)而言,使用Sobel算子近似计算导数的缺点是精度比较低
Scbarr滤波器同sobel滤波器一样快,但是准确率更高,故当你利用3x3滤波器实现图像度量的时候应该使用Scharr滤波器
四.非最大信号抑制
边缘的信号很强,但边缘只能有一个,不能说你这么很宽都是边缘,所以要对非边缘的一些像素进行压制就是如果在它的方向上面如果它不是最大值的话我们就把它去掉,切向是角度的方向,法向是它跟垂直90度的向,在它左右两边如果值都小于当前的这个那么我们就把它去掉对图像所有的点都做非最大信号抑制θ取值范围在-π/2到π/2加上π/2就是0到π之间,这个θ就是说我们这个梯度的方向是什么,梯度在向哪个方向上面变化率最大x方向变化很大的话θ就会很小,就得到变化的趋势向哪一个方向,这就是我们梯度的方向,我们跟梯度垂直的方向上面在它的左边和右边和中间的值相比,如果都比它小左边和右边都去掉,中间最大值这个保留,这个叫做非最大信号抑制,反正就是把较小的去掉了
五.高低阈值输出二值图像 、
高低阈值链接:t1,t2为阈值,凡是高于t2的都保留,凡是低于t1的都丢弃,从高于t2的像素出发,凡是大于t1而相互连接的,都保留。最终得到一个输出二值图像。
推荐的高低阈值比值为T2:T1=3:1/2:1其中t2为高阈值
API:
Canny( InputArray src, // 8-bit的输入图像
OutputArray edges,// 输出边缘图像, 一般都是二值图像,背景是黑色
double threshold1,// 低阈值,常取高阈值的1/2或者1/3
double threshold2,// 高阈值
int aptertureSize,// Soble算子的size,通常3x3,取值3
bool L2gradient // 选择 true表示是L2来归一化,否则用L1归一化 ,一般用L1参数为false)
import cv2 as cv
import numpy as np
def contours_demo(image):
dst=cv.GaussianBlur(image,(3,3),0)#高斯
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)#取灰度
ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)#二值
cv.imshow("binnay image",binary)
cloneImage,contours,heriachy=cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE,)#克隆 轮廓
# contours = cv.FindContours(binay, cv.CreateMemStorage(0), cv.CV_RETR_LIST, cv.CV_CHAIN_APPROX_SIMPLE, (0, 0))
for i ,contour in enumerate(contours):
cv.drawContours(image,contours,i,(0,0,255),2)# 最后一个参数如果为-1 那么就填充轮廓
print(i)
cv.imshow("detect_image",image)
src=cv.imread("G:\software\pythonproject\coin.jpg")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image",src)
contours_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()