提取步骤

  • 输入彩色图像*imread**
  • 转换为灰度图像cvtColor
  • 转换为二值图像adaptiveThreshold
  • 定义结构元素(异形卷积核)
  • 开操作(腐蚀+膨胀)提取水平与垂直线,消除斜线

adaptiveThreshold 自适应阈值操作API
void 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;
}

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐