提取步骤
- 输入彩色图像
- 转换为灰度图像--cvtcolor
- 转换为二值图像--adaptiveThreshold(Threshold)
- 定义结构元素 *(重点)
- 开操作(腐蚀+膨胀)提取,水平和垂直线
二值图像
二值图像是指在图像中,灰度等级只有两种,也就是说,图像中的任何像素不是0就是1,再无其他过渡的灰度值。
图像二值化的作用是为了方便提取图像中的信息,二值图像在进行计算机识别时可以增加识别效率。
参数说明
src:源图像,可以为8位的灰度图,也可以为32位的彩色图像。(两者由区别)
dst:输出图像
thresh:阈值
maxval:dst图像中最大值
type:阈值类型,可以具体类型如下:
编号 | 阈值类型枚举 | 注意 |
1 | THRESH_BINARY |
|
2 | THRESH_BINARY_INV |
|
3 | THRESH_TRUNC |
|
4 | THRESH_TOZERO |
|
5 | THRESH_TOZERO_INV |
|
6 | THRESH_MASK | 不支持 |
7 | THRESH_OTSU | 不支持32位 |
8 | THRESH_TRIANGLE | 不支持32位 |
具体如下表
生成关系如下表
Otsu算法原理
Otsu算法(大津法或最大类间方差法)使用的是聚类的思想,把图像的灰度数按灰度级分成2个部分,使得两个部分之间的灰度值差异最大,每个部分之间的灰度差异最小,通过方差的计算来寻找一个合适的灰度级别来划分。 所以可以在二值化的时候采用otsu算法来自动选取阈值进行二值化。otsu算法被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响。因此,使类间方差最大的分割意味着错分概率最小。
设t为设定的阈值。
w0 | 分开后前景像素点数占图像的比例 |
u0 | 分开后前景像素点的平均灰度 |
w1 | 分开后背景像素点数占图像的比例 |
u1 | 分开后背景像素点的平均灰度 |
图像总平均灰度为: u = w0∗u0 + w1∗u1
从L个灰度级遍历 t,使得 t 为某个值的时候,前景和背景的方差最大,则 这个 t 值便是我们要求得的阈值。其中,方差的计算公式如下:
g = wo∗(u0−u)∗(u0−u) + w1∗(u1−u)∗(u1−u)
此公式计算量较大,可以采用:
g = w0∗w1∗(u0−u1)∗(u0−u1)
由于Otsu算法是对图像的灰度级进行聚类,因此在执行Otsu算法之前,需要计算该图像的灰度直方图。
//自动化找阈值的两种方法
threshold(src2, dst,0,255,THRESH_OTSU|thresh_type);
threshold(src2, dst, 0, 255,THRESH_TRIANGLE|thresh_type);
adaptiveThreshold
自适应二值化介绍:
opencv中adaptiveThreshold函数分析:
参数:
_src 要二值化的灰度图
_dst 二值化后的图
maxValue 二值化后要设置的那个值
method 块计算的方法(ADAPTIVE_THRESH_MEAN_C 平均值,ADAPTIVE_THRESH_GAUSSIAN_C 高斯分布加权和)
type 二值化类型(CV_THRESH_BINARY 大于为最大值,CV_THRESH_BINARY_INV 小于为最大值)
blockSize 块大小(奇数,大于1,通过计算每个像素周围(blocksize x blocksize)大小像素块的加权均值并减去常量C得到。)
delta 差值(负值也可以)
如果使用平均的方法,则所有像素周围的权值相同;如果使用高斯的方法,则(x,y)周围的像素的权值则根据其到中心点的距离通过高斯方程得到。
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src1, src2, dst,dst1;
src1 = imread("C:\\Users\\马迎伟\\Desktop\\hs.png");
if (src1.empty())
{
cout << "could not find src1" << endl;
}
namedWindow("input",CV_WINDOW_AUTOSIZE);
imshow("input",src1);
//先对 src1 转换成单通道灰度值
cvtColor(src1,src2,CV_BGR2GRAY);
//imshow("x",src2);
//只有转换成灰度才能将图像进行二值化处理(自适应阈值操作) ~为取反操作,有助于后面步骤的进行
adaptiveThreshold(src2,dst,255,CV_ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY,15,2);//15为块大小,通过对15*15的矩阵进行CV_ADAPTIVE_THRESH_MEAN_C操作,求和平均与c比较
//对二值化的图像进行 开操作
bitwise_not(dst, dst);
imshow("s", dst);
//水平结构元素
Mat hkernel = getStructuringElement(MORPH_RECT,Size(dst.cols/16,1));
//垂直结构元素
//Mat skernel = getStructuringElement(MORPH_RECT,Size(1,dst.rows / 16));
morphologyEx(dst, dst1, CV_MOP_TOPHAT, hkernel, Point(-1, -1));
imshow("wa",dst1);
waitKey(0);
return 0;
}