1. 程式人生 > >影象處理1---Moravec運算元

影象處理1---Moravec運算元

# include<opencv2/opencv.hpp>//在新版本的opencv中,所有的標頭檔案都已經涵蓋在本行標頭檔案中了
# include <iostream>
# include <stdio.h>
# include <math.h>
using namespace std;
using namespace cv;

uchar get_pix(Mat *src, int x, int y)
{
	uchar *pt = src->ptr<uchar>(y);
	return pt[x];
}

void set_mat_pix(Mat *src, int x, int y, float value)
{
	uchar * pt = src->ptr<uchar>(y);
	pt[x] = value;
}

//Moravec運算元
void Moravec(Mat * src, int kenal, float threshold, vector<Point>*cor_point)
{
	int half_kenal = kenal / 2;
	float min_value;
	Mat dst(src->size(), CV_8UC1, Scalar(0));
	//定義Mat的格式方法:Mat a(行,列,型別,值);
	//                  Mat a.creat(行,列,型別);
	for (int y = half_kenal; y < src->rows - half_kenal; y++)
	{
		for (int x = half_kenal; x < src->cols - half_kenal; x++)
		{
			float move_value[4] = { {0} };
			for (int win = -half_kenal; win < half_kenal; win++)
			{
				//0°方向方差
				move_value[0] += powf(get_pix(src, x + win, y) - get_pix(src, x + win + 1, y), 2);
				//45°方向方差
				move_value[1] += powf(get_pix(src, x + win, y + win) - get_pix(src, x + win + 1, y + win + 1), 2);
				move_value[2] += pow(get_pix(src, x, y + win) - get_pix(src, x, y + win + 1), 2);//90°方向變化量
				move_value[3] += pow(get_pix(src, x - win, y + win) - get_pix(src, x - win - 1, y + win + 1), 2);
			}
			min_value = move_value[0];
			for (int i = 0; i < 4; i++)
			{
				if (min_value > move_value[i])
					min_value = move_value[i];
				else
					continue;
			}
			set_mat_pix(&dst, x, y, min_value);
		}
	}
	//獲取角點座標
	float max_value; int flag; Point max_loc; float value;
	for (int y = half_kenal; y < src->rows - half_kenal; )
	{
		for (int x = half_kenal; x < src->cols - half_kenal; )
		{
			max_value = 0;
			value = 0;
			flag = 0;
			max_loc.x = -1;
			max_loc.y = -1;
			//計算點(x,y)位中心的kenal的區域性最大值
			for (int winy = -half_kenal; winy <= half_kenal; winy++)
			{
				for (int winx = -half_kenal; winx <= half_kenal; winx++)
				{
					value = get_pix(&dst, x + winx, y + winy);
					if (value > max_value)
					{
						max_value = value;
						max_loc.x = x + winx;
						max_loc.y = y + winy;
						flag = 1;
					}

				}
			}
			//判斷是否是角點
			if (flag == 1 && (max_value > threshold))
			{
				cor_point->push_back(max_loc);
			}
			x += kenal;
		}
		y += kenal;
	}


}

int main()
{
	Mat src, src_gray;
	int k = 5;
	float threshold = 254;
	vector<Point>corner_point;
	vector<Point>::iterator itr;
	src = imread("1.png");

	if (src.empty())
	{
		cout << "載入影象失敗!!!" << endl;
		return -1;
	}

	cvtColor(src, src_gray, COLOR_RGB2GRAY);//將影象轉換為灰度影象
	Moravec(&src_gray, k, threshold, &corner_point);
	for (itr = corner_point.begin(); itr < corner_point.end(); itr++)
		circle(src, *itr, 5, Scalar(255, 0, 0));
	namedWindow("win");
	imshow("win", src);
	waitKey(0);

	return 0;
}

/***************************************總結*************************************************************
	Point local==>local.x,local.y:可以記錄點的座標;
	vector<Point> corner_point;定義一個Point型別的容器(動態陣列),
	使用corner_point.push_back(變數名)將數值壓入陣列;
	vector迭代器的生成及使用:vector<Point>::iterator itr;定義迭代器名稱
							for(itr = itr.begin(); itr<itr.end(); itr++)
********************************************************************************************************/