opencv入门基础(c++)【二】

opencv入门基础(c++)

  • 七.绘制形状与文字
    • 7.1使用cv::Point与cv::Scalar
    • 7.2绘制线、矩形、园、椭圆等基本几何形状
      • 绘制线
      • 绘制矩形
      • 绘制椭圆
      • 绘制圆
      • 绘制填充图形
    • 7.3绘制文字
    • 7.4随机数生成cv::RNG
  • 八、模糊图像一
    • 8.1模糊原理
    • 8.2相关API
      • 均值模糊
      • 高斯模糊
  • 九、图像模糊二
    • 9.1中值滤波
    • 9.2双边滤波
    • 9.3相关API
  • 十、膨胀与腐蚀
    • 10.1形态学操作(morphology operators)-膨胀
    • 10.2形态学操作-腐蚀
    • 10.3相关API
    • 10.4动态调整结构元素大小
  • 十一、形态学操作
    • 11.1开操作- open
    • 11.2闭操作-close
    • 11.3形态学梯度- Morphological Gradient
    • 11.4顶帽 – top hat
    • 11.5黑帽
    • 11.6相关API
  • 十二、形态学操作应用-提取水平与垂直线
    • 12.1原理方法
      • 二值图像与灰度图像上的膨胀操作
      • 二值图像与灰度图像上的腐蚀操作
    • 12.2结构元素
    • 12.3提取步骤
      • 转换为二值图像 – adaptiveThreshold
      • 定义结构元素
      • 后处理

七.绘制形状与文字

使用cv::Point与cv::Scalar
绘制线、矩形、园、椭圆等基本几何形状
随机生成与绘制文本

7.1使用cv::Point与cv::Scalar

Point表示2D平面上一个点x,y
Point p;
p.x = 10;
p.y = 8;
or
p = Pont(10,8);
Scalar表示四个元素的向量
Scalar(a, b, c);// a = blue, b = green, c = red表示RGB三个通道

7.2绘制线、矩形、园、椭圆等基本几何形状

画线 cv::line (LINE_4\LINE_8\LINE_AA)【LINE_AA反锯齿-画圆】
画椭圆cv::ellipse
画矩形cv::rectangle 画矩形Rect(x,y,width,height)
画圆cv::circle
ellipse(Mat img,Point(x,y),Size(a,b),angle,0,360,Scalar(,,),thickness,lineType);
画填充cv::fillPoly

绘制线

#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1;
void Myline();
int main()
{

	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)
	
	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}
	Myline();
	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);
	
	
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}

void Myline() {
	Point p1 = Point(20, 30);//位置坐标
	Point p2;
	p2.x = 300;
	p2.y = 300;
	Scalar color = Scalar(0, 0, 255);
	line(src1, p1, p2, color, 1, LINE_8);
}

绘制矩形

#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1;

void MyRectangle();
int main()
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)
	
	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}
	MyRectangle();
	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);
	
	
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}

void MyRectangle() {
	Rect rect = Rect(200, 50, 200, 200);
	Scalar color = Scalar(0, 0, 225);
	rectangle(src1, rect, color, 2, LINE_8);
}

绘制椭圆

#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1;
void MyOval();
int main()
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)
	
	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}
	MyOval();
	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);
	
	
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}

void MyOval() {
	Scalar color = Scalar(0, 250, 0);
	ellipse(src1, Point(src1.cols / 2, src1.rows / 2), Point(src1.cols / 6, src1.rows / 7), 45, 0, 360, color, 2, LINE_8);
}

绘制圆

#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1;
void MyCircle();
int main()
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)
	
	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}
	MyCircle();
	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);
	
	
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}

void MyCircle() {
	Scalar color = Scalar(130, 0, 0);
	circle(src1, Point(src1.cols / 2, src1.rows / 2), 100, color, 2, LINE_8);
}

绘制填充图形

#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1;
void MyCircle();
void MyPolygon();
int main()
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)
	
	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}
	MyCircle();
	MyPolygon();
	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);
	
	
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}

void MyCircle() {
	Scalar color = Scalar(130, 0, 0);
	circle(src1, Point(src1.cols / 2, src1.rows / 2), 100, color, 2, LINE_8);
}
void MyPolygon() {
	Scalar color = Scalar(250, 0, 0);
	Point pts[1][5];
	pts[0][0] = Point(100, 100);
	pts[0][1] = Point(100, 200);
	pts[0][2] = Point(200, 200);
	pts[0][3] = Point(200, 100);
	pts[0][4] = Point(100, 100);

	const Point* ppts[] = { pts[0] };
	int npt[] = { 5 };
	fillPoly(src1, ppts, npt, 1, color, 8);

}

7.3绘制文字

putText函数 中设置fontFace(cv::HersheyFonts),

  • fontFace, CV_FONT_HERSHEY_PLAIN
  • fontScale , 1.0, 2.0~ 8.0
#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1;

int main()
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)
	
	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}
	
	putText(src1, "hhhhhhhhhhhhhhhh",Point(300,300), FONT_HERSHEY_SIMPLEX, 2, Scalar(0, 0, 255), 4, 8);
	/*注释
	在src1图片上,显示hhhhhhhhhhhhhhhh,位置在(300,300),字体类型为FONT_HERSHEY_SIMPLEX,字体大小为2,颜色为红色,字体厚度为4,线型默认为8.
	*/

	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);
	
	
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}

7.4随机数生成cv::RNG

生成高斯随机数gaussian (double sigma)
生成正态分布随机数uniform (int a, int b)

#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1;
void RandomLineDemo();
int main()
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)
	
	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}
	
	putText(src1, "hhhhhhhhhhhhhhhh",Point(300,300), FONT_HERSHEY_SIMPLEX, 2, Scalar(0, 0, 255), 4, 8);
	/*注释
	在src1图片上,显示hhhhhhhhhhhhhhhh,位置在(300,300),字体类型为FONT_HERSHEY_SIMPLEX,字体大小为2,颜色为红色,字体厚度为4,线型默认为8.
	*/

	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);
	
	RandomLineDemo();
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}
void RandomLineDemo() {
	RNG rng(12345);
	Point pt1;
	Point pt2;
	Mat bg = Mat::zeros(src1.size(), src1.type());
	namedWindow("random line demo", WINDOW_AUTOSIZE);
	for (int i = 0; i < 100000; i++) {
		pt1.x = rng.uniform(0, src1.cols);
		pt2.x = rng.uniform(0, src1.cols);
		pt1.y = rng.uniform(0, src1.rows);
		pt2.y = rng.uniform(0, src1.rows);
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		if (waitKey(50) > 0) {
			break;
		}
		line(bg, pt1, pt2, color, 1, 8);
		imshow("random line demo", bg);
	}
}

八、模糊图像一

8.1模糊原理

Smooth/Blur 是图像处理中最简单和常用的操作之一
使用该操作的原因之一就为了给图像预处理时候减低噪声
使用Smooth/Blur操作其背后是数学的卷积计算

通常这些卷积算子计算都是线性操作,所以又叫线性滤波

opencv入门基础(c++)【二】_第1张图片
假设有6x6的图像像素点矩阵。

卷积过程:6x6上面是个3x3的窗口,从左向右,从上向下移动,黄色的每个像个像素点值之和取平均值赋给中心红色像素作为它卷积处理之后新的像素值。每次移动一个像素格。

归一化盒子滤波(均值滤波
opencv入门基础(c++)【二】_第2张图片
高斯滤波
在这里插入图片描述

8.2相关API

均值模糊

- blur(Mat src, Mat dst, Size(xradius, yradius), Point(-1,-1));//Point(-1,-1))不要去改

在这里插入图片描述

#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1,dst;
void RandomLineDemo();
int main()
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)
	
	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}
	


	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);
	blur(src1, dst, Size(15, 15), Point(-1, -1));//均值模糊

	char output_win[] = "output image";
	namedWindow(output_win, WINDOW_AUTOSIZE);
	imshow(output_win, dst);
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}


高斯模糊

- GaussianBlur(Mat src, Mat dst, Size(11, 11), sigmax, sigmay);

其中Size(x, y), x, y 必须是正数而且是奇数
sigmax, sigmay:横波和滤波的大小;
Ksize为高斯滤波器模板大小

计算高斯卷积核

#include "iostream"
#include "math.h"

using namespace std;
//using namespace cv;

//******************高斯卷积核生成函数*************************
//第一个参数gaus是一个指向含有3个double类型数组的指针;
//第二个参数size是高斯卷积核的尺寸大小;
//第三个参数sigma是卷积核的标准差
//*************************************************************
void GetGaussianKernel(double **gaus, const int size, const double sigma);

int main(int argc, char *argv[])
{
	int size = 5; //定义卷积核大小
	double **gaus = new double *[size];
	for (int i = 0; i < size; i++)
	{
		gaus[i] = new double[size];  //动态生成矩阵
	}
	cout << "尺寸 = 3*3,Sigma = 1,高斯卷积核参数为:" << endl;
	GetGaussianKernel(gaus, 3, 1); //生成3*3 大小高斯卷积核,Sigma=1;	
	cout << "尺寸 = 5*5,Sigma =1,高斯卷积核参数为:" << endl;
	GetGaussianKernel(gaus, 5, 1); //生成5*5 大小高斯卷积核,Sigma=1;
	cout << "尺寸 = 5*5,Sigma =5,高斯卷积核参数为:" << endl;
	GetGaussianKernel(gaus, 5, 5); //生成5*5 大小高斯卷积核,Sigma=1;
	cout << "尺寸 = 5*5,Sigma =7,高斯卷积核参数为:" << endl;
	GetGaussianKernel(gaus, 5, 7); //生成5*5 大小高斯卷积核,Sigma=1;
	system("pause");
	return 0;
}

//******************高斯卷积核生成函数*************************
void GetGaussianKernel(double **gaus, const int size, const double sigma)
{
	const double PI = 4.0*atan(1.0); //圆周率π赋值
	int center = size / 2;
	double sum = 0;
	for (int i = 0; i < size; i++)
	{
		for (int j = 0; j < size; j++)
		{
			gaus[i][j] = (1 / (2 * PI*sigma*sigma))*exp(-((i - center)*(i - center) + (j - center)*(j - center)) / (2 * sigma*sigma));
			sum += gaus[i][j];
		}
	}

	for (int i = 0; i < size; i++)
	{
		for (int j = 0; j < size; j++)
		{
			gaus[i][j] /= sum;
			cout << gaus[i][j] << "  ";
		}
		cout << endl << endl;
	}
	return;
}

#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1,dst;
void RandomLineDemo();
int main()
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)
	
	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}

	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);
	//blur(src1, dst, Size(15, 15), Point(-1, -1));
	GaussianBlur(src1,dst, Size(5, 5), 10, 10);
	char output_win[] = "output image";
	namedWindow(output_win, WINDOW_AUTOSIZE);
	imshow(output_win, dst);
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}


九、图像模糊二

9.1中值滤波

统计排序滤波器
中值对椒盐噪声有很好的抑制作用
opencv入门基础(c++)【二】_第3张图片

#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1,dst;
void RandomLineDemo();
int main()
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)
	
	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}

	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);
	//blur(src1, dst, Size(15, 15), Point(-1, -1));
	//GaussianBlur(src1,dst, Size(5, 5), 10, 10);
	medianBlur( src1, dst, 5);
	char output_win[] = "output image";
	namedWindow(output_win, WINDOW_AUTOSIZE);
	imshow(output_win, dst);
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}


9.2双边滤波

均值模糊无法克服边缘像素信息丢失缺陷。原因是均值滤波是基于平均权重

高斯模糊部分克服了该缺陷,但是无法完全避免,因为没有考虑像素值的不同

高斯双边模糊 – 是边缘保留的滤波方法,避免了边缘信息丢失,保留了图像轮廓不变
opencv入门基础(c++)【二】_第4张图片

#include 
#include
#include

//using namespace std;
//using namespace cv;

void RandomLineDemo();
int main()
{
	cv::Mat src1, dst;
	src1 = cv::imread("C:/Users/Admin/Desktop/1.png");	//读取图片(使用图片的绝对路径)
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}

	//char input_win[] = "input image";
	cv::namedWindow("input_win",cv:: WINDOW_AUTOSIZE);
	imshow("input_win", src1);
	//blur(src1, dst, Size(3, 3), Point(-1, -1));//均值滤波
	//GaussianBlur(src1,dst, Size(15, 15), 1, 1);//高斯滤波
	//medianBlur( src1, dst, 5);//中值滤波
	//bilateralFilter(src1, dst, 15, 70, 3);//双边滤波
	char output_win[] = "output image";
	cv::namedWindow(output_win, cv::WINDOW_AUTOSIZE);
	imshow(output_win, dst);
	cv::waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}









9.3相关API

中值模糊
medianBlur(Mat src, Mat dest, ksize)
双边模糊
bilateralFilter(src, dest, d=15, 150, 3);

15 –计算的半径,半径之内的像数都会被纳入计算,如果提供-1 则根据sigma space参数取值
150 – sigma color 决定多少差值之内的像素会被计算
3 – sigma space 如果d的值大于0则声明无效,否则根据它来计算d值
中值模糊的ksize大小必须是大于1而且必须是奇数。

十、膨胀与腐蚀

10.1形态学操作(morphology operators)-膨胀

图像形态学操作 – 基于形状的一系列图像处理操作的合集,主要是基于集合论基础上的形态学数学
形态学有四个基本操作:腐蚀、膨胀、开、闭
膨胀与腐蚀是图像处理中最常用的形态学操作手段

跟卷积操作类似,假设有图像A和结构元素B,结构元素B在A上面移动,其中B定义其中心为锚点,计算B覆盖下A的最大像素值用来替换锚点的像素,其中B作为结构体可以是任意形状

白色膨胀,人物变小
opencv入门基础(c++)【二】_第5张图片

10.2形态学操作-腐蚀

腐蚀跟膨胀操作的过程类似,唯一不同的是以最小值替换锚点重叠下图像的像素值
人物腐蚀背景变大
opencv入门基础(c++)【二】_第6张图片

10.3相关API

getStructuringElement(int shape, Size ksize, Point anchor)

  • 形状 (MORPH_RECT \MORPH_CROSS \MORPH_ELLIPSE)
  • 大小
  • 锚点 默认是Point(-1, -1)意思就是中心像素
    dilate(src, dst, kernel)
    在这里插入图片描述

erode(src, dst, kernel)

在这里插入图片描述

10.4动态调整结构元素大小

TrackBar – createTrackbar(const String & trackbarname, const String winName, int* value, int count, Trackbarcallback func, void* userdata=0)
其中最中要的是 callback 函数功能。如果设置为NULL就是说只有值update,但是不会调用callback的函数。

#include  
#include  
using namespace cv;

Mat src, dst;
char OUTPUT_WIN[] = "output image";
int element_size = 3;
int max_size = 21;
void CallBack_Demo(int, void*);
int main(int argc, char** argv) {
	
	src = imread("D:/vcprojects/images/test1.png");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input image", CV_WINDOW_AUTOSIZE);
	imshow("input image", src);

	namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);
	createTrackbar("Element Size :", OUTPUT_WIN, &element_size, max_size, CallBack_Demo);
	CallBack_Demo(0, 0);

	waitKey(0);
	return 0;
}

void CallBack_Demo(int, void*) {
	int s = element_size * 2 + 1;
	Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
	// dilate(src, dst, structureElement, Point(-1, -1), 1);
	erode(src, dst, structureElement);
	imshow(OUTPUT_WIN, dst);
	return;
}

十一、形态学操作

11.1开操作- open

先腐蚀后膨胀
在这里插入图片描述
可以去掉小的对象,假设对象是前景色,背景是黑色
opencv入门基础(c++)【二】_第7张图片




#include 
#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1,dst;

char output_win[] = "output image";
int main(int argc, char** argv)
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}

	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);






	Mat kernel = getStructuringElement(MORPH_RECT, Size(30, 30), Point(-1, -1));
	morphologyEx(src1, dst, MORPH_OPEN, kernel);

	namedWindow(output_win, WINDOW_AUTOSIZE);
	imshow(output_win, dst);

	
	//imshow(output_win, dst);
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}





11.2闭操作-close

先膨胀后腐蚀(bin2)
在这里插入图片描述
可以填充小的洞(fill hole),假设对象是前景色,背景是黑色
opencv入门基础(c++)【二】_第8张图片




#include 
#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1,dst;

char output_win[] = "output image";
int main(int argc, char** argv)
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}

	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);






	Mat kernel = getStructuringElement(MORPH_RECT, Size(30, 30), Point(-1, -1));
	morphologyEx(src1, dst, MORPH_CLOSE, kernel);

	namedWindow(output_win, WINDOW_AUTOSIZE);
	imshow(output_win, dst);

	
	//imshow(output_win, dst);
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}





11.3形态学梯度- Morphological Gradient

膨胀减去腐蚀
在这里插入图片描述
又称为基本梯度(其它还包括-内部梯度、方向梯度)
opencv入门基础(c++)【二】_第9张图片




#include 
#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1,dst;

char output_win[] = "output image";
int main(int argc, char** argv)
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}

	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);






	Mat kernel = getStructuringElement(MORPH_RECT, Size(30, 30), Point(-1, -1));
	morphologyEx(src1, dst, MORPH_GRADIENT, kernel);

	namedWindow(output_win, WINDOW_AUTOSIZE);
	imshow(output_win, dst);

	
	//imshow(output_win, dst);
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}





11.4顶帽 – top hat

顶帽 是原图像与开操作之间的差值图像
opencv入门基础(c++)【二】_第10张图片




#include 
#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1,dst;

char output_win[] = "output image";
int main(int argc, char** argv)
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}

	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);






	Mat kernel = getStructuringElement(MORPH_RECT, Size(30, 30), Point(-1, -1));
	morphologyEx(src1, dst, MORPH_TOPHAT, kernel);

	namedWindow(output_win, WINDOW_AUTOSIZE);
	imshow(output_win, dst);

	
	//imshow(output_win, dst);
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}

11.5黑帽

黑帽是闭操作图像与源图像的差值图像

opencv入门基础(c++)【二】_第11张图片




#include 
#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1,dst;

char output_win[] = "output image";
int main(int argc, char** argv)
{
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}

	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src1);






	Mat kernel = getStructuringElement(MORPH_RECT, Size(30, 30), Point(-1, -1));
	morphologyEx(src1, dst, MORPH_BLACKHAT, kernel);

	namedWindow(output_win, WINDOW_AUTOSIZE);
	imshow(output_win, dst);

	
	//imshow(output_win, dst);
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}





11.6相关API

morphologyEx(src, dest, CV_MOP_BLACKHAT, kernel);

  • Mat src – 输入图像

  • Mat dest – 输出结果

  • int OPT
    MORPH_OPEN – 开运算
    MORPH_CLOSE – 闭运算
    MORPH_GRADIENT - 形态学梯度
    MORPH_TOPHAT - 顶帽
    MORPH_BLACKHAT - 黑帽

  • Mat kernel 结构元素

  • int Iteration 迭代次数,默认是1

十二、形态学操作应用-提取水平与垂直线

12.1原理方法

图像形态学操作时候,可以通过自定义的结构元素实现结构元素
对输入图像一些对象敏感、另外一些对象不敏感,这样就会让敏
感的对象改变而不敏感的对象保留输出。通过使用两个最基本的
形态学操作 – 膨胀与腐蚀,使用不同的结构元素实现对输入图像
的操作、得到想要的结果。

  • 膨胀,输出的像素值是结构元素覆盖下输入图像的最大像素值
  • 腐蚀,输出的像素值是结构元素覆盖下输入图像的最小像素值

二值图像与灰度图像上的膨胀操作

opencv入门基础(c++)【二】_第12张图片

二值图像与灰度图像上的腐蚀操作

opencv入门基础(c++)【二】_第13张图片

12.2结构元素

上述膨胀与腐蚀过程可以使用任意的结构元素
常见的形状:矩形、园、直线、磁盘形状、砖石形状等各种自定义形状opencv入门基础(c++)【二】_第14张图片

12.3提取步骤

输入图像彩色图像 imread
转换为灰度图像 – cvtColor
转换为二值图像 – adaptiveThreshold
定义结构元素
开操作 (腐蚀+膨胀)提取 水平与垂直线

转换为二值图像 – adaptiveThreshold

adaptiveThreshold(
Mat src, // 输入的灰度图像
Mat dest, // 二值图像
double maxValue, // 二值图像最大值
int adaptiveMethod // 自适应方法,只能其中之一 –
// ADAPTIVE_THRESH_MEAN_C , ADAPTIVE_THRESH_GAUSSIAN_C
int thresholdType,// 阈值类型
int blockSize, // 块大小
double C // 常量C 可以是正数,0,负数
)

opencv入门基础(c++)【二】_第15张图片
在这里插入图片描述

定义结构元素

一个像素宽的水平线 - 水平长度 width/30
一个像素宽的垂直线 – 垂直长度 height/30

后处理

bitwise_not(Mat bin, Mat dst)像素取反操作,255 – SrcPixel
模糊(blur)







#include 
#include 
#include
#include
using namespace std;
using namespace cv;
Mat src1,dst;

char output_win[] = "output image";
int main(int argc, char** argv)
{    /*第一步:imread导入彩色图像*/
	 src1 = imread("C:/Users/Admin/Desktop/1.jpg");	//读取图片(使用图片的绝对路径)	
	if (src1.empty()) {
		printf("could not find the image!\n");
		return -1;
	}
	/*第二步:转为灰度图像cvtColor(src1, dst, COLOR_BGR2GRAY);*/
	if (src1.channels() == 1) {
		dst = src1;
	}
	else {
		cvtColor(src1, dst, COLOR_BGR2GRAY);
	}
	/*第三步:转为二值图像*/
	Mat binImg;
	adaptiveThreshold(dst, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);

	/*第四步:定义结构元素*/
	// 水平结构元素
	Mat hline = getStructuringElement(MORPH_RECT, Size(src1.cols / 16, 1), Point(-1, -1));
	// 垂直结构元素
	Mat vline = getStructuringElement(MORPH_RECT, Size(1, src1.rows / 16), Point(-1, -1));
	// 矩形结构
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));

	/*第五步:开操作 (腐蚀+膨胀)提取 水平与垂直线*/
	Mat temp;
	erode(binImg, temp, vline);
	dilate(temp, dst, vline);
	/*第六步:一些可有可无的后处理*/
	bitwise_not(dst, dst);//像素取反操作
	blur(dst, dst, Size(3, 3), Point(-1, -1));//模糊
	char input_win[] = "input image";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win,dst);


	namedWindow(output_win, WINDOW_AUTOSIZE);
	imshow(output_win, binImg);

	
	//imshow(output_win, dst);
	waitKey(0);//不加此语句图片会一闪而过
	system("path");
	getchar();
	return 0;
}





}





你可能感兴趣的:(opencv入门基础(c++)【二】)