【OpenCV:从零到一】11:提取水平线、垂直线(自适应阈值)

前言
这是我《OpenCV:从零到一》专栏的第十一篇博客,想看跟多请戳
本文概要
adaptiveThreshold
bitwise_not
提取步骤
输入图像彩色图像 imread
转换为灰度图像 – cvtColor
转换为二值图像 – adaptiveThreshold
定义结构元素
开操作 (腐蚀+膨胀)提取 水平与垂直线
案例代码
大概内容:提取边缘(点)或者水平线 。

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
int main(int argc, char** argv) {
	Mat src, dst;
	src = imread("D:\\86186\\Documents\\opencv\\lena.jpg");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}

	char INPUT_WIN[] = "input image";
	char OUTPUT_WIN[] = "result image";
	namedWindow(INPUT_WIN, WINDOW_AUTOSIZE);
	imshow(INPUT_WIN, src);

	Mat gray_src;
	cvtColor(src, gray_src, COLOR_BGR2GRAY);
	imshow("gray image", gray_src);

	Mat binImg;
	adaptiveThreshold(~gray_src, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
	imshow("binary image", binImg);

	// 水平结构元素
	Mat hline = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1));
	// 垂直结构元素
	Mat vline = getStructuringElement(MORPH_RECT, Size(1, src.rows / 16), Point(-1, -1));
	// 矩形结构
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));

	Mat temp;
	erode(binImg, temp, kernel);
	dilate(temp, dst, kernel);
	// morphologyEx(binImg, dst, CV_MOP_OPEN, vline);
	bitwise_not(dst, dst);
	//blur(dst, dst, Size(3, 3), Point(-1, -1));
	imshow("Final Result", dst);

	waitKey(0);
	return 0;
}

运行效果:
这里展现点和水平线的效果。

adaptiveThreshold(~gray_src, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);在这里插入图片描述
adaptiveThreshold(gray_src, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);//玄学,效果变差了
在这里插入图片描述
morphologyEx(binImg, dst, CV_MOP_OPEN, vline);//提取水平线
在这里插入图片描述
解析及注意事项

  • adaptiveThreshold里的玄学:老师发的源文件里面的输入图像前面加了一个"~"符号,然后效果就好了很多,查阅了相关文档也没有发现有这个用法,(关键是程序竟然不报错),目前不知道为什么,好神奇。在这里插入图片描述
  • adaptiveThreshold是一个自适应的阈值分隔函数,自适应方法只有两个参数分别是MEAN_C和GAUSSIAN_C在这里插入图片描述
  • 分隔的方法有很多种,具体看下面的图片。ThresholdTypes在这里插入图片描述
    在这里插入图片描述
  • 阈值分隔的原图像必须是灰度的图像。
  • 上面的内容都属于形态学的综合运用
  • CV_BGR2GRAY 在opencv4中是COLOR_BGR2GRAY,有些特别,可以了解一下。

全注释代码

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
int main(int argc, char** argv) {
	Mat src, dst;
	src = imread("D:\\86186\\Documents\\opencv\\lena.jpg");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}

	char INPUT_WIN[] = "input image";
	char OUTPUT_WIN[] = "result image";
	namedWindow(INPUT_WIN, WINDOW_AUTOSIZE);
	imshow(INPUT_WIN, src);

	Mat gray_src;
	cvtColor(src, gray_src, COLOR_BGR2GRAY);//提取图片的直线需要用到阈值操作,因此必须使用灰度图像
	imshow("gray image", gray_src);

	Mat binImg;
	adaptiveThreshold(~gray_src, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);//自适应阈值
	//adaptiveThreshold(gray_src, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
	/*
	The function transforms a grayscale image to a binary image according to the formulae:
	InputArray 	src,
	OutputArray 	dst,
	double 	maxValue,//	Non-zero value assigned to the pixels for which the condition is satisfied//像素值最大的值
	int 	adaptiveMethod,//Adaptive thresholding algorithm to use, see AdaptiveThresholdTypes.
							//只可以填ADAPTIVE_THRESH_GAUSSIAN_C和ADAPTIVE_THRESH_MEAN_C
						  //The BORDER_REPLICATE | BORDER_ISOLATED is used to process boundaries.
	int 	thresholdType,//Thresholding type that must be either THRESH_BINARY or THRESH_BINARY_INV, see ThresholdTypes.
	int 	blockSize,//Size of a pixel neighborhood that is used to calculate a threshold value for the pixel: 3, 5, 7, and so on.
	double 	C //Constant subtracted from the mean or weighted mean (see the details below). Normally, it is positive but may be zero or negative as well.
	*/
	imshow("binary image", binImg);

	// 水平结构元素
	Mat hline = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1));
	// 垂直结构元素
	Mat vline = getStructuringElement(MORPH_RECT, Size(1, src.rows / 16), Point(-1, -1));
	// 矩形结构
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));

	//开操作
	Mat temp;
	erode(binImg, temp, kernel);//kernel换成hline或者vline的话就可以实现提取水平线和垂直线了
	dilate(temp, dst, kernel);
	//erode(binImg, temp, vline);
	//dilate(temp, dst, vline);
	//上面两句也可以换成下面这一句
	// morphologyEx(binImg, dst, CV_MOP_OPEN, vline);
	

	bitwise_not(dst, dst);//Inverts every bit of an array.
	//blur(dst, dst, Size(3, 3), Point(-1, -1));
	imshow("Final Result", dst);

	waitKey(0);
	return 0;
}

翻译笔记
bitwise_not 按位取not
Adaptive 自适应的
Threshold 阈值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章