提取步骤
- 输入彩色图像*imread**
- 转换为灰度图像cvtColor
- 转换为二值图像adaptiveThreshold
- 定义结构元素(异形卷积核)
- 开操作(腐蚀+膨胀)提取水平与垂直线,消除斜线
adaptiveThreshold 自适应阈值操作APIvoid adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C);
参数介绍
- 第一个参数,
InputArray src
,原图,即输入图像,是一个8位单通道的图像(灰度图); - 第二个参数,
OutputArray dst
,目标图像,与原图像具有同样的尺寸与类型; - 第三个参数,
double maxValue
,分配给满足条件的像素的非零值(最大值要么为0,要么为该值); - 第四个参数,
int adaptiveMethod
,自适应阈值的方法,通常有以下几种方法;
- (1)ADAPTIVE_THRESH_MEAN_C,平均值滤波。
- (2)ADAPTIVE_THRESH_GAUSSIAN_C,高斯滤波
- 第五个参数,
int thresholdType
,阈值的类型必须是以下两种类型,
- (1)THRESH_BINARY,正向二值化,大于阈值为最大值,小于为0
- (2)THRESH_BINARY_INV ,反向二值化,大于阈值为0,小于为最大值
- 第六个参数,
int blockSize
,像素邻域的大小(卷积核),用来计算像素的阈值,blockSize
必须为奇数,例如,3,5,7等等; - 第七个参数,
double C
,从平均数或加权平均数减去常量。通常,它是正的,但也可能是零或负数。
算法原理
二值图像:整个图像只有两种值,0和第三个参数
maxValue
(非黑即白)
第四个参数决定图像自适应采样方式,均值滤波还是高斯滤波(加权),二值产生原理:如果以均值方式自适应化,中心点的值与(卷积核内部区域均值减去第七个参数的值的差)进行比较,如果第五个参数选择为正向二值化,则大于差值的像素为第三个参数的值,小于差值的像素为0。反之亦然。
处理技巧
- 去除竖线用横向长方形作为卷积核,执行开操作
- 去除横线用竖向长方形作为卷积核,执行开操作
- 去除斜线用正方形作为卷积核,执行开操作
代码示例
#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
#define Pic_Path "E:\\picture\\"
#define Pic_Name "16.png"
using namespace std;
int main(int argc, char **argv)
{
//获取图片完整路径及名称
string pic = string(Pic_Path) + string(Pic_Name);
cout << pic << endl;
//获取原始图片
cv::Mat src;
src = cv::imread(pic.c_str());
if (src.empty())
return - 1;
cv::imshow("原始图片", src);
cv::Mat gray_src;
cv::cvtColor(src, gray_src,cv::COLOR_BGR2GRAY);
cv::imshow("灰度图片", gray_src);
cv::Mat bin_src;
cv::adaptiveThreshold(~gray_src, bin_src, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 15, -2);
cv::imshow("二值图像", bin_src);
cv::Mat hline = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(src.cols / 16, 1), cv::Point(-1, -1));
cv::Mat vline = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1, src.rows / 16), cv::Point(-1, -1));
cv::Mat rect = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3), cv::Point(-1, -1));
cv::Mat tmp,dst;
//可用开操作代替
cv::erode(bin_src, tmp, hline);
cv::dilate(tmp, dst, hline);
cv::blur(dst, dst, cv::Size(3, 3));//均值模糊使图片过渡自然
cv::imshow("消除竖线图像", ~dst);//反向显示 图片更清晰
//可用开操作代替
cv::erode(bin_src, tmp, vline);
cv::dilate(tmp, dst, vline);
cv::blur(dst, dst, cv::Size(3, 3)); //均值模糊使图片过渡自然
cv::imshow("消除横线图像", ~dst);//反向显示 图片更清晰
cv::morphologyEx(bin_src, dst, CV_MOP_OPEN, rect);
cv::imshow("消除斜线图片", ~dst);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}