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++上的非常多的疑問,還專門找了參考書給我,非常感謝!

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