【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 閾值

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