视觉培训5 学习图像处理

目录

一、图像预处理

二、转化为灰度图

三、二值化

四、开闭运算

1. 开运算:腐蚀->膨胀

​编辑

2. 闭运算:膨胀->腐蚀

​编辑


一、图像预处理

在实战中,由于环境光的干扰,如果直接对图片进行算法处理,会错误的提取多余的特征,导致算法的准确度和速度大大降低。我们可以通过调整摄像机曝光或者使用亮度处理的函数,减少背景光的干扰。

原图:

调整图像对比度和亮度

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char* argv[]){
    // 读入图像,判断读入是否成功
	string fileName = samples::findFile("C:\\Users\\86139\\Desktop\\target.png");
	Mat src = imread(fileName, IMREAD_COLOR);
	if (src.empty())
	{
		fprintf(stderr, "failed to load image: %s\n", fileName);
		system("pause");
		return EXIT_FAILURE;
	}

    Mat dst1, dst2, dst3;
	dst1 = Mat::zeros(src.size(), src.type());
	double alpha = 1.0;
	double beta = 0.0;
	double gama = 1.0;

    // 提示并输入 α  β  γ  的值
	cout << " Basic Linear Transforms " << endl;
	cout << "-------------------------" << endl;
	cout << "* Enter the alpha value [1.0-3.0]: "; cin >> alpha;
	cout << "* Enter the beta value [0-100]: ";    cin >> beta;
	cout << "* Enter the gamma value [-1,1]: ";    cin >> gama;

    // 直接使用循环遍历每一个像素,应用公式
	double t1 = (double)getTickCount();
	for (int row=0;row<src.rows;++row)
		for(int col=0;col<src.cols;++col)
			for (int channel = 0; channel < src.channels(); ++channel)
			{
				dst1.at<Vec3b>(row, col)[channel] = saturate_cast<uchar>(alpha * src.at<Vec3b>(row, col)[channel] + beta);
			}
	double time1 = ((double)getTickCount() - t1) / getTickFrequency();
	cout << "Method by pixel use time:" << time1 << "(ms)" << endl;

    // 调用 convertTo() 函数调整对比度和亮度
	double t2 = (double)getTickCount();
	src.convertTo(dst2, -1, alpha, beta);
	double time2 = ((double)getTickCount() - t2) / getTickFrequency();
	cout << "Method by pixel use time:" << time2 << "(ms)" << endl;

    // 构建查找表
	Mat lookUpTable(1, 256, CV_8U);
	uchar* p = lookUpTable.ptr();
	for (int i = 0; i < 256; ++i)
		p[i] = saturate_cast<uchar>(pow(i / 255.0, gama) * 255.0);

   // 使用查找表进行对比度亮度调整
	double t3 = (double)getTickCount();
	LUT(src, lookUpTable, dst3);
	double time3 = ((double)getTickCount() - t3) / getTickFrequency();
	cout << "Method by Gamma correct use time:" << time3 << "(ms)" << endl;

    // 调整窗体大小,显示调整效果
	namedWindow("original", WINDOW_NORMAL);
	resizeWindow("original", Size(src.cols, src.rows));
	imshow("original", src);
	namedWindow("pixel set", WINDOW_NORMAL);
	resizeWindow("pixel set", Size(src.cols, src.rows));
	imshow("pixel set", dst1);
	namedWindow("convertTo", WINDOW_NORMAL);
	resizeWindow("convertTo", Size(src.cols, src.rows));
	imshow("convertTo", dst2);
	namedWindow("Gamma correct", WINDOW_NORMAL);
	resizeWindow("Gamma correct", Size(src.cols, src.rows));
	imshow("Gamma correct", dst3);
	waitKey(0);
	system("pause");
	return EXIT_SUCCESS;
}

设定值:alphe:2        beta:40        gamma:0.5

效果:

设置像素后:

 调整对比度和亮度:

 设置gamma后:

其实这个原图就已经被处理过了,这里只是试验一下

二、转化为灰度图

我们可以通过opencv自带的split函数,将一个3通道的rgb图像转换成3个单通道图像,通过通道相减的方式获得灰度图。

由于不知道这个通道相减是什么意思,就先把BGR三个通道都先显示了,自己尝试了一下

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

using namespace cv;
using namespace std;

int main(int argc, char* argv[]){
	Mat image;
	image = imread("C:\\Users\\86139\\Desktop\\target.png");
	if (image.data == 0)
	{
		cout << "读取错误" << endl;
	}
	imshow("original", image);

	vector<Mat> channels;
	split(image, channels);
	imshow("B", channels[0]); //蓝色通道
	imshow("G", channels[1]); //绿色通道
	imshow("R", channels[2]); //红色通道
	imshow("B-G", channels[0] - channels[1]); //蓝减绿
	imshow("B-R", channels[0] - channels[2]); //蓝减红
	imshow("G-R", channels[1] - channels[2]); //绿减红
	imshow("B-G-R", channels[0] - channels[1] - channels[2]); //蓝减绿减红

	waitKey(0);

	return 0;
}

蓝色通道:

 绿色通道:

 红色通道:

 下面尝试了一下通道相减,但是我不知道是哪个减哪个,就都试了一下

蓝减绿:

 蓝减红:

 绿减红:

 因为灯的颜色是蓝色的所以我试了一下蓝减绿和红:

 不知道是需要哪种的结果

通道相减是我们常用的将图像转为灰度图的方法,该方法可以进一步帮助我们去除不需要的信息。当然你也可以选择其余的方法,如直接使用cvtColor函数

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

using namespace cv;
using namespace std;

int main(int argc, char* argv[]){
	Mat img;
	img = imread("C:\\Users\\86139\\Desktop\\target.png");
	if (img.empty())
	{
		printf("could not load the picture...");
	}

	// 将彩色图转换为灰度图,常采用以下方法:
	Mat gray_img;
	cvtColor(img, gray_img, COLOR_RGB2GRAY); //颜色转换函数
	//		原图	新图		RGB转GRAY

	namedWindow("gary_img", WINDOW_AUTOSIZE);
	imshow("gary_img", gray_img);

	waitKey(0);

	return 0;
}

效果图:

三、二值化

图像二值化( ImageBinarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。相当于将输入图像中阈值外的像素全部置0,使得阈值内目标凸出,便于PC进行灯条识别。

二值化的效果会因为上一步是否进行通道相减或其他操作以及threshold函数中阈值设置而产生偏差。下面直接利用之前见过灰度化之后的图像进行二值化。

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

using namespace cv;
using namespace std;

int main(int argc, char* argv[]){
	Mat img;
	img = imread("C:\\Users\\86139\\Desktop\\target1.png");
	if (img.empty())
	{
		printf("could not load the picture...");
	}

	// 转为二值图
	threshold(img, img, 100, 255, THRESH_BINARY);

	imshow("Binarization", img);
	waitKey(0);

	return 0;
}

效果图:

四、开闭运算

散布着一些小的噪声物体。连续的开和闭运算可以有效地改善这种情况。有时需要经过多次腐蚀之后再加上相同次数的膨胀,才可以产生比较好的效果。

膨胀:相当于增肥,将锚点以外的部分增加一圈像素点

腐蚀:相当于减肥,将锚点以外的部分去掉

1. 开运算:腐蚀->膨胀

先腐蚀后膨胀的过程称为开运算。用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。

看一下单独使用开运算后的结果:

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

using namespace cv;
using namespace std;

int main(int argc, char* argv[]){
	Mat img;
	img = imread("C:\\Users\\86139\\Desktop\\target2.png");
	if (img.empty())
	{
		printf("could not load the picture...");
	}

	Mat element;
	Mat dstImage;

    element = getStructuringElement(MORPH_RECT, Size(4, 4)); //Size选择要处理的精度,越大处理的越多

    morphologyEx(img, dstImage, MORPH_OPEN, element);

	imshow("open", dstImage);
	waitKey(0);

	return 0;
}

2. 闭运算:膨胀->腐蚀

先膨胀后腐蚀的过程称为闭运算。用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积。

看一下单独使用闭运算后的结果:

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

using namespace cv;
using namespace std;

int main(int argc, char* argv[]){
	Mat img;
	img = imread("C:\\Users\\86139\\Desktop\\target2.png");
	if (img.empty())
	{
		printf("could not load the picture...");
	}

	Mat element;
	Mat dstImage;

    element = getStructuringElement(MORPH_RECT, Size(4, 4)); //Size选择要处理的精度,越大处理的越多

	morphologyEx(img, dstImage, MORPH_CLOSE, element);

	imshow("close", dstImage);
	waitKey(0);

	return 0;
}

 其实开运算和闭运算只是morphologyEx里面参数是MORPH_OPEN还是MORPH_CLOSE的区别,看一下使用开闭运算后的结果吧

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

using namespace cv;
using namespace std;

int main(int argc, char* argv[]){
	Mat img;
	img = imread("C:\\Users\\86139\\Desktop\\target2.png");
	if (img.empty())
	{
		printf("could not load the picture...");
	}

	Mat element_open;
	Mat element_close;
	Mat dstImage_open;
	Mat dstImage_close;

    element_open = getStructuringElement(MORPH_RECT, Size(4, 4)); //Size选择要处理的精度,越大处理的越多
	element_close = getStructuringElement(MORPH_RECT, Size(3, 3));

    morphologyEx(img, dstImage_open, MORPH_OPEN, element_open);
	morphologyEx(dstImage_open, dstImage_close, MORPH_CLOSE, element_close);

	imshow("open-close", dstImage_close);
	waitKey(0);

	return 0;
}

  • 9
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世界函数

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值