EAIDK-610 图像处理初步

今天介绍了简单的图像处理算法,基本属于OpenCV的入门算法。

之前使用过python版本的OpenCV,大部分操作已经被封装成可直接调用的函数,卷积可以直接通过numpy来实现,而C++中除了若干简单的滤波算法之外,没有其他的函数了。不过相比于Python,C++的好处在于速度快,对于对帧率要求比较高的设备来说,C++的优势还是非常明显。

由于各类算法大同小异(尤其是各类使用二维卷积的算法),因此只贴出主要结构和分析

本次用到的源文件为:

  •    mipi_demo.cpp         (main()函数所在文件)
  •    mipi_cam.cpp           (mipi摄像头驱动)
  •    image_handle.cpp     (图像处理函数所在文件)

摄像头驱动不做修改。

main函数所在文件只需要在while(1)循环中加入你写好的图像处理函数即可

主要介绍几个典型的图像处理代码:

1.直方图均衡

void histogram_equalization (const Mat src, Mat& dst)//直方图均衡
{
	Mat gray,gray_end;//创建三个矩阵

	if (!src.data || !dst.data)//一个判断
		return;
	
	double probability_gray[256] = {0};
	//建立矩阵
	gray.create(cv::Size(RGA_ALIGN(src.cols, 16), RGA_ALIGN(src.rows, 16)), CV_8UC1);//RGA_ALIGN用于对齐格式
	gray_end.create(cv::Size(RGA_ALIGN(src.cols, 16), RGA_ALIGN(src.rows, 16)), CV_8UC1);

	//rgb转灰度
	rgb_to_gray(src, gray);
	
	for (int i = 0 + 1; i < src.rows - 1; i++)//统计频次
	{
		for (int j = 0 + 1; j < src.cols - 1; j++)
		{
			probability_gray[gray.at<uchar>(i, j)] += 1;
		}
	}
	//计算累计概率
	for (int i = 1; i < 256; i++)
	{
			probability_gray[i] += probability_gray[i-1];
	}
	for (int i = 0; i < 256; i++)
	{
		probability_gray[i] /= 307200.0;
	}
	
	for (int i = 0 + 1; i < src.rows - 1; i++)
	{
		for (int j = 0 + 1; j < src.cols - 1; j++)
		{
			gray_end.at<uchar>(i, j) = (uchar)(probability_gray[gray.at<uchar>(i, j)] * 255.0);
		}
	}
	fcv::cvtColor(gray_end, dst, CV_GRAY2BGR);//灰度转bgr
} 

一些补充:

1 这段代码在计算流程上还可以优化,但可读性会下降(不需要除以307200,而是考虑255,一起计算,每帧可以减少307200次乘法计算)

2 这是将彩图转换灰度之后做的直方图均衡处理,如果要保持彩图,需要对RGB三个通道的矩阵分别做直方图均衡

2 卷积(以锐化效果为例)

void sharpen_flitering(const Mat src, Mat &dst)//锐化滤波器
{
	Mat gray gray_end;//创建2个矩阵
	signed char kernel[3][3] = {
		{ 0, -1, 0},
		{ -1, 5, 1},
		{ 0, -1, 0}};

	if (!src.data || !dst.data)//一个判断
		return;

	//建立矩阵
	gray.create(cv::Size(RGA_ALIGN(src.cols, 16), RGA_ALIGN(src.rows, 16)), CV_8UC1);//RGA_ALIGN用于对齐格式

	gray_end.create(cv::Size(RGA_ALIGN(src.cols, 16), RGA_ALIGN(src.rows, 16)), CV_8UC1);

	//rgb转灰度
	rgb_to_gray(src, gray);

	for (int i = 0+1; i < src.rows-1; i++)
	{
		//uchar* p1 = gray.ptr<uchar>(i);//灰度图的一行
		//uchar* p2 = gray_reverse.ptr<uchar>(i);//
		uchar* q = gray_end.ptr<uchar>(i);
		for (int j = 0+1; j < src.cols-1; j++)
		{
			gray_end.at<uchar>(i, j) = 0;
			gray_end.at<uchar>(i, j) += gray.at<uchar>(i - 1, j - 1) * kernel[0][0];
			gray_end.at<uchar>(i, j) += gray.at<uchar>(i - 1, j - 0) * kernel[0][1];
			gray_end.at<uchar>(i, j) += gray.at<uchar>(i - 1, j + 1) * kernel[0][2];
			gray_end.at<uchar>(i, j) += gray.at<uchar>(i - 0, j - 1) * kernel[1][0];
			gray_end.at<uchar>(i, j) += gray.at<uchar>(i - 0, j - 0) * kernel[1][1];
			gray_end.at<uchar>(i, j) += gray.at<uchar>(i - 0, j + 1) * kernel[1][2];
			gray_end.at<uchar>(i, j) += gray.at<uchar>(i + 1, j - 1) * kernel[2][0];
			gray_end.at<uchar>(i, j) += gray.at<uchar>(i + 1, j - 0) * kernel[2][1];
			gray_end.at<uchar>(i, j) += gray.at<uchar>(i + 1, j + 1) * kernel[2][2];
		}
	}
	fcv::cvtColor(gray_end, dst, CV_GRAY2BGR);//灰度转bgr

}

一些补充:

1 代码仍可优化

2 修改卷积核,可以实现其他的效果

gray_end.at<uchar>(i, j) ,这句话表示gray_end的第(i,j)个像素的值

感谢:

非常感谢2位老师和杭宇学长的指导,尤其是杭宇学长,解决了我关于C++上的非常多的疑问,还专门找了参考书给我,非常感谢!

发布了44 篇原创文章 · 获赞 203 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/ReadAir/article/details/86617358