计算机视觉

将图片压缩成灰度图像的几种方法:

1.人眼对于彩色的感觉到亮度感觉的转换,这是一个心理学问题,有一个公式:

Grey = 0.299R + 0.587G + 0.114*B

2.直接提取单通道图

Grey=R or G or B

3.取平均值:

Grey=(R+G+B)/3


图像预处理

1.灰度值变换

方法1:线性比例缩放

f(x)=ax+b
当|a|>1时,对比度增加,
当|a|<0时,对比度减小,若a为负数灰度值反转。
当b>0时,亮度增加,反之亮度减小

方法2:灰度值直方图均衡化

使用的前提时灰度值差异较大
对于一幅图片,先要统计他像素中各个灰度级的出现情况,之后用直方图来描绘。灰度直方图描述的时一个图片中某个灰度在图片中所占的比例。
灰度直方图的两个峰,数值大的是前景,数值小的是背景,中间的是最佳阈值区间

2.图像平滑

方法1:
均值滤波
方法2:

高斯滤波:

高斯滤波

理想状态下的滤波器:1.线性 2.与位置无关 3.可以控制参数 4.可以多次执行 5.系数阵旋转对称

方法3:

中值滤波:这时一种非线性的滤波,在处理随机噪声上有优势


中值滤波

3.矫正

对图像进行旋转、平移、放大的操作。


二值化应用最广泛的取阈值点方法

最大类间方差法(otus大津法):

适合用于双峰图,最小峰是前景,最大峰值时背景,中间值为最佳阈值区间。假设有一个点可以正好把一幅图分为两大类,这两大类的均值为m1与m2假设的最优点为mg,p1、p2表示的时前景背景所占的比例,默认为1:1。目的就是找到最大的方差σ,因为方差表示的是离散程度,找到一个分类点使得离散程度最高,就可以成功分离开前景和背景。


最大类间方差

opencv实现

参数说明
src:源图像,可以为8位的灰度图,也可以为32位的彩色图像。(两者由区别)
dst:输出图像
thresh:阈值
maxval:dst图像中最大值
type:阈值类型,可以具体类型如下:

双阈值分割可以用两次单阈值分割叠加:
threshold(img2, out1, 50, 255, THRESH_BINARY); //大阈值对源灰度图像进行反二进制阈值化操作 threshold(img2, out2,140, 255, THRESH_BINARY_INV);//thresh:阈值,maxval:输出图像中最大值 bitwise_and(out1, out2, img2); //对像素加和


特征提取

区域特征

从区域自身提取来的特征
最简单的方法是计算区域的面积,其可以用计算区域内点的个数来代替

行程编码

在一个联通的二值图中,把图像转换成矩阵后,每一行只存储连续点的开头元素位置和结尾元素位置
有一个字符串“aaabccddddd”,经过行程 编码后可以用“3a1b2c5d

灰度图的方差:可以判断图片是否模糊(要规定感受野的)
灰度图的亮度:来描述图片的连读

几何不变矩

矩是对变量分布和形态分布的一组度量,n阶矩被定义为一变量的n次方与其概率密度函数之积的积分

变量的一阶原始矩等价于[数学期望]、二至四阶中心矩被定义为[方差]、[偏度]



HU不变矩具有平移旋转和尺度不变性,这里表述的数域转移到了二维




形态学

六种基本操作

1.闵科夫斯基加法

在结构元上定义一个中心点,把这个结构元当刷子以中心点为基准遍历目标,目标没有的点就加上去。


2.膨胀:

对结构元先进行对称再进行闵可夫斯基加法,因为结构元大多数是中心对称的,所以一般不区分膨胀和闵可夫斯基加法。

3.闵科夫斯基减法:

膨胀的对偶运算


4.腐蚀:闵可夫斯基加法的对偶
5.闭运算

先膨胀后腐蚀

闭运算

闭运算的效果图如下图所示:

我们也可以得到关于闭运算的几点结论:
(1)闭运算能够填平小湖(即小孔),弥合小裂缝,而总的位置和形状不变。
(2)闭运算是通过填充图像的凹角来滤波图像的。
(3)结构元素大小的不同将导致滤波效果的不同。
(4)不同结构元素的选择导致了不同的分割。

6.开运算

先腐蚀后膨胀
开运算的效果图如下图所示:

我们可以得到关于开运算的几点结论:
(1)开运算能够除去孤立的小点,毛刺和小桥,而总的位置和形状不便。
(2)开运算是一个基于几何运算的滤波器。
(3)结构元素大小的不同将导致滤波效果的不同。
(4)不同的结构元素的选择导致了不同的分割,即提取出不同的特征。

边界提取的原理:

通过对目标图像进行腐蚀和膨胀处理,比较结果图像与原图像的差别来实现。

内边界的提取利用图像的腐蚀处理得到原图像的一个收缩,再将收缩结果与目标图像进行异或运算,实现差值部分的提取,

外边界提取先对图像进行膨胀处理,然后用膨胀结果与原目标图像进行异或运算,也就是求膨胀结果与原目标图像的差集

关键就是找到合适的结构元

一些基本术语

刷子:用来处理对象的图像,通常是较小的,相当于滤波器、窗口
击中:两个对象有交集
对称:一般是关于某一个点的旋转对称


边缘检测

定义:

边缘:局部差异性强,一定不是闭合的
边界:一定是闭合的
轮廓:是在大尺度,在δ比较大的情况下,全局来看,也不一定是闭合的

边缘的分类:

阶梯状边缘:图像灰度值不同的相邻区间内
脉冲状边缘:在该处图像的灰度值会有突增
屋顶状边缘:灰度值的上升和下降都比较平滑,这三类边缘的检测是越来越难的


三类边缘

梯度

对梯度的定义可以有很多,梯度反映的图像在该点,增加最快的方向。可以用梯度局部的最大值来规定边缘。


常见对梯度的定义

算子

定义:

广义算子就是一个映射,一维中可以由一个数变成另一个数,就是一个函数;二维中可以把一个矩阵转换成另一个矩阵、或者压缩到一维下的
另一个数值
狭义的算子是函数到函数
泛函是函数到数字


像是罗伯特算子适合一个倾斜45,135的阶梯、脉冲边缘,普瑞维特算子适合横竖的边缘。

几种常见的二阶算子(大部分奇数规模)

首先模板基本要求是核为正数,所有系数的和为0,如拉普拉斯算子:


canny边缘检测步骤

1.先要进行降噪,对图像进行个平滑处理,这里选取的是五阶的高斯平滑算子

2.刚才的sobel算子,来计算梯度的幅值和方向



3.非极大值抑制:再池化一次,将边缘描述成少像素的细线条
4.滞后阈值: 滞后阈值需要两个阈值(高阈值和低阈值):

如果某一像素位置的幅值超过 高 阈值, 该像素被保留为边缘像素。
如果某一像素位置的幅值小于 低 阈值, 该像素被排除。
如果某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于 高 阈值的像素时被保留。

Canny 推荐的 高:低 阈值比在 2:1 到3:1之间。

    cvtColor(srcImage, srcGray, CV_BGR2GRAY);//灰度化
GaussianBlur(srcGray, srcGray, Size(3,3),1, 1);//高斯, 120, 255
//blur(srcGray, srcGray, Size(3, 3));
imshow("GaussianBlur", srcGray);
//Canny检测
int edgeThresh = 80;
Mat Canny_result;
Canny(srcGray, Canny_result, 120, 250,3);
imshow("Canny_result", Canny_result);
waitKey(0);

我考虑了用膨胀和腐蚀去点条形码,效果一般

Mat element1 = getStructuringElement(MORPH_CROSS, Size(5, 5));
Mat element2 = getStructuringElement(MORPH_CROSS, Size(6, 6));
Mat element3 = getStructuringElement(MORPH_CROSS, Size(2, 2));
dilate(Canny_result, Canny_result, element1);
erode(Canny_result, Canny_result, element2);
dilate(Canny_result, Canny_result, element1);
erode(Canny_result, Canny_result, element3);
erode(Canny_result, Canny_result, element3);
dilate(Canny_result, Canny_result, element3);

LBP提取纹理(不受光照影响)

LBPH(Local Binary Pattern Histogram) 局部二值模式直方图,是一种用来描述图像局部纹理特征的算子;它具有旋转不变性和灰度不变性等显著的优点,原始的LBP算子定义为在33的窗口内,以窗口中心像素为阈值,将相邻的8个像素的灰度值与其进行比较,若周围像素值大于中心像素值,则该像素点的位置被标记为1,否则为0。这样,33邻域内的8个点经比较可产生8位二进制数(通常转换为十进制数即LBP码,共256种),即得到该窗口中心像素点的LBP值,并用这个值来反映该区域的纹理信息。LBP算法可以很好的提取图片局部的纹理特征,由于其选择的是阈值函数, LBP算法收光照影响不明显。

void LBP(IplImage* src, IplImage* dst)

{

int width = src->width;

int height = src->height;

for (int j = 1; j < width - 1; j++)

{

for (int i = 1; i < height - 1; i++)

{

uchar neighborhood[8] = { 0 };

neighborhood[7] = CV_IMAGE_ELEM(src, uchar, i - 1, j - 1);

neighborhood[6] = CV_IMAGE_ELEM(src, uchar, i - 1, j);

neighborhood[5] = CV_IMAGE_ELEM(src, uchar, i - 1, j + 1);

neighborhood[4] = CV_IMAGE_ELEM(src, uchar, i, j - 1);

neighborhood[3] = CV_IMAGE_ELEM(src, uchar, i, j + 1);

neighborhood[2] = CV_IMAGE_ELEM(src, uchar, i + 1, j - 1);

neighborhood[1] = CV_IMAGE_ELEM(src, uchar, i + 1, j);

neighborhood[0] = CV_IMAGE_ELEM(src, uchar, i + 1, j + 1);

uchar center = CV_IMAGE_ELEM(src, uchar, i, j);

uchar temp = 0;

for (int k = 0; k < 8; k++)

{

temp += (neighborhood[k] >= center) << k;

}

CV_IMAGE_ELEM(dst, uchar, i, j) = temp;

}

}

}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容