harris角点检测(c++)

harris.h

#ifndef HARRIS_H_
#define HARRIS_H_
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <string>
#include <conio.h>
#include <easyx.h>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
typedef unsigned char uchar;
typedef vector<vector<long> >  LONG_2DVEC;
typedef vector<vector<float> > FLOAT_2DVEC;
typedef vector<vector<uchar> > UCHAR_2DVEC;
typedef vector<vector<int> >   INT_2DVEC;

typedef vector<long>  LONG_VEC;
typedef vector<float> FLOAT_VEC;
typedef vector<int>   INT_VEC;

typedef vector<vector<int> >   CORNER_VEC;

void  ConvertStringToWchar(string sToMatch, wchar_t * lpwsz);
IMAGE ConvertBGRToGRAY(IMAGE srcImage);
IMAGE SobelGradintX(IMAGE grayImage);
IMAGE SobelGradintY(IMAGE grayImage);

INT_2DVEC SobelGradint2DVectorX(IMAGE grayImage);
INT_2DVEC SobelGradint2DVectorY(IMAGE grayImage);


LONG_2DVEC  SobelXX(IMAGE GXImage);
LONG_2DVEC  SobelXY(IMAGE GXImage, IMAGE GYImage);
LONG_2DVEC  SobelYY(IMAGE GYImage);

FLOAT_2DVEC HarrisResponse(LONG_2DVEC GradXX, LONG_2DVEC GradXY, LONG_2DVEC GradYY, float k);
UCHAR_2DVEC DataNormalize(FLOAT_2DVEC Response);
CORNER_VEC  LocalMaxValue(UCHAR_2DVEC Response);
CORNER_VEC  HarrisCornerDetection(IMAGE srcImage);
void PaintCorner(CORNER_VEC CORNER_VECTOR, IMAGE srcIMAGE);

#endif // !HARRIS_H_

harris.c

#include "harris.h"

void  ConvertStringToWchar(string sToMatch, wchar_t * lpwsz)
{
	// 计算转换后宽字符串的长度。(不包含字符串结束符) 
	int iWLen = MultiByteToWideChar(CP_ACP, 0, sToMatch.c_str(), sToMatch.size(), 0, 0); 
	MultiByteToWideChar(CP_ACP, 0, sToMatch.c_str(), sToMatch.size(), lpwsz, iWLen); // 正式转换。 
	lpwsz[iWLen] = L'\0';

}

IMAGE ConvertBGRToGRAY(IMAGE srcImage) {
	int rows = srcImage.getheight();
	int cols = srcImage.getwidth();
	IMAGE grayImage = srcImage;
	DWORD* GRAY_PTR = GetImageBuffer(&grayImage);
	vector<uchar> vec(cols, 0);
	vector<vector<uchar> > Vec(rows, vec);
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			*GRAY_PTR = BGR(*GRAY_PTR);//显存是RGB,图像在内存存储为
			Vec.at(i).at(j) = (GetRValue(*GRAY_PTR) * 299 + GetGValue(*GRAY_PTR) * 587 + GetBValue(*GRAY_PTR) * 114  +500) / 1000;
			*GRAY_PTR = RGB(Vec.at(i).at(j), Vec.at(i).at(j), Vec.at(i).at(j));
			GRAY_PTR++;

		}
	}
	GRAY_PTR -= rows * cols;
	return grayImage;
}

IMAGE SobelGradintX(IMAGE srcImage) {
	
	int rows = srcImage.getheight();
	int cols = srcImage.getwidth();
	DWORD* PTR = GetImageBuffer(&srcImage);

	IMAGE GXImage = srcImage;
	DWORD* GX_PTR = GetImageBuffer(&GXImage);

	int Grad = 0;
	for (int i = 1; i < rows - 1; i++)
	{
		for (int j = 1; j < cols - 1; j++)
		{
			Grad = (GetRValue(*(PTR+(i-1)* cols+j-1)) + 2* GetRValue(*(PTR + (i-1)*cols + j))
				+ GetRValue(*(PTR+(i-1) * cols + j+1)))- (GetRValue(*(PTR+(i+1)* cols+j-1)) +
					2 * GetRValue(*(PTR+(i+1)* cols+j)) + GetRValue(*(PTR+(i+1)* cols+j +1)));
			*(GX_PTR + i * cols +j) = RGB(abs(Grad), abs(Grad), abs(Grad));
		}
	}

	return GXImage;
}
INT_2DVEC SobelGradint2DVectorX(IMAGE grayImage) {
	
	int rows = grayImage.getheight();
	int cols = grayImage.getwidth();
	INT_VEC vec(cols,0);
	INT_2DVEC Vec(rows,vec);
	DWORD* PTR = GetImageBuffer(&grayImage);


	int Grad = 0;
	for (int i = 1; i < rows - 1; i++)
	{
		for (int j = 1; j < cols - 1; j++)
		{
			Grad = (GetRValue(*(PTR + (i - 1)* cols + j - 1)) + 2 * GetRValue(*(PTR + (i - 1)*cols + j))
				+ GetRValue(*(PTR + (i - 1) * cols + j + 1))) - (GetRValue(*(PTR + (i + 1)* cols + j - 1)) +
					2 * GetRValue(*(PTR + (i + 1)* cols + j)) + GetRValue(*(PTR + (i + 1)* cols + j + 1)));
			Vec.at(i).at(j) = abs(Grad);
		}
	}
	return Vec;
}

IMAGE SobelGradintY(IMAGE srcImage) {
	int rows = srcImage.getheight();
	int cols = srcImage.getwidth();

	DWORD* PTR = GetImageBuffer(&srcImage);

	IMAGE GYImage = srcImage;
	DWORD* GY_PTR = GetImageBuffer(&GYImage);

	int Grad = 0;
	for (int i = 1; i < rows - 1; i++)
	{
		for (int j = 1; j < cols - 1; j++)
		{
			Grad = (GetRValue(*(PTR + (i - 1)* cols + j + 1)) + 2 * GetRValue(*(PTR + i * cols + j + 1)) 
			   + GetRValue (*(PTR + (i + 1)* cols + j + 1)))- (GetRValue(*(PTR + (i - 1)* cols + j - 1))
				+ 2 * GetRValue(*(PTR + i * cols + j - 1)) + GetRValue(*(PTR + (i + 1)* cols + j - 1)));
			*(GY_PTR + i * cols + j) = RGB(abs(Grad), abs(Grad), abs(Grad));
		}
	}

	return GYImage;
}
INT_2DVEC SobelGradint2DVectorY(IMAGE srcImage) {
	int rows = srcImage.getheight();
	int cols = srcImage.getwidth();
	INT_VEC vec(cols, 0);
	INT_2DVEC Vec(rows, vec);
	DWORD* PTR = GetImageBuffer(&srcImage);



	int Grad = 0;
	for (int i = 1; i < rows - 1; i++)
	{
		for (int j = 1; j < cols - 1; j++)
		{
			Grad = (GetRValue(*(PTR + (i - 1)* cols + j + 1)) + 2 * GetRValue(*(PTR + i * cols + j + 1))
				+ GetRValue(*(PTR + (i + 1)* cols + j + 1))) - (GetRValue(*(PTR + (i - 1)* cols + j - 1))
					+ 2 * GetRValue(*(PTR + i * cols + j - 1)) + GetRValue(*(PTR + (i + 1)* cols + j - 1)));
			Vec.at(i).at(j) = abs(Grad);
		}
	}

	return Vec;
}

LONG_2DVEC  SobelXX(IMAGE GXImage) {
	int rows = GXImage.getheight();
	int cols = GXImage.getwidth();
	DWORD* GX_PTR = GetImageBuffer(&GXImage);

	
	LONG_2DVEC Vec ;
	LONG_VEC vec;
	int GradX = 0;
	
	for (int i = 0; i < rows ; i++)
	{	
		for (int j = 0; j < cols; j++)
		{
			GradX = GetRValue(*(GX_PTR + i * cols + j));
			vec.push_back(GradX * GradX);
			
		}
		Vec.push_back(vec);
		vec.clear();
	}
	return Vec;
}

LONG_2DVEC  SobelXY(IMAGE GXImage, IMAGE GYImage) {
	int rows = GXImage.getheight();
	int cols = GXImage.getwidth();
	DWORD* GX_PTR = GetImageBuffer(&GXImage);
	DWORD* GY_PTR = GetImageBuffer(&GYImage);


	LONG_2DVEC Vec;
	LONG_VEC vec;
	int GradX = 0;
	int GradY = 0;

	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			GradX = GetRValue(*(GX_PTR + i * cols + j));
			GradY = GetRValue(*(GY_PTR + i * cols + j));
			vec.push_back(GradX * GradY);
		}
		Vec.push_back(vec);
		vec.clear();
	}
	return Vec;
}

LONG_2DVEC  SobelYY(IMAGE GYImage) {
	int rows = GYImage.getheight();
	int cols = GYImage.getwidth();
	DWORD* PTR = GetImageBuffer(&GYImage);


	LONG_2DVEC Vec;
	LONG_VEC vec;
	int Grad = 0;

	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			Grad = GetRValue(*(PTR + i * cols + j));
			vec.push_back(Grad * Grad);

		}
		Vec.push_back(vec);
		vec.clear();
	}
	return Vec;
}

FLOAT_2DVEC HarrisResponse(LONG_2DVEC GradXX, LONG_2DVEC GradXY, LONG_2DVEC GradYY,float k) {
	int rows = GradXX.size();
	int cols = GradXX.at(0).size();
	FLOAT_2DVEC Vec;
	FLOAT_VEC vec;
	float result = 0;

	for (int i = 0; i < rows; i++)
	{
		vec.clear();
		for (int j = 0; j <cols; j++)
		{
			long a = GradXX.at(i).at(j);
			long b = GradYY.at(i).at(j);
			long c = GradXY.at(i).at(j);
			result= abs(a * b - c * c - k * (a + b)*(a + b));
			vec.push_back(result);
		}
		Vec.push_back(vec);

	}
	return Vec;
}
UCHAR_2DVEC DataNormalize(FLOAT_2DVEC Response) {
	FLOAT_2DVEC::iterator It1;
	

	int max = 0;
	int min = 0;

	
	for (It1 = Response.begin(); It1 != Response.end(); It1++) {
		if (max < *max_element((*It1).begin(), (*It1).end() )) {
			max = *max_element((*It1).begin(), (*It1).end());
		}
		else {
			max = max;
		}
		if (min > *max_element((*It1).begin(), (*It1).end() )) {
			min = *max_element((*It1).begin(), (*It1).end());
		}
		else {
			min = min;
		}
	}
	UCHAR_2DVEC ResponseNorm;
	vector<uchar> vec;
	FLOAT_VEC::iterator It2;
	for (It1 = Response.begin(); It1 != Response.end(); It1++) {
		vec.clear();
		for (It2 = (*It1).begin(); It2 != (*It1).end(); It2++) {
			vec.push_back(ceil(((*It2) / (max - min))* 255));
		}
		ResponseNorm.push_back(vec);
	}

	return ResponseNorm;
}

CORNER_VEC LocalMaxValue(UCHAR_2DVEC ResponseNorm) {
	int rows = ResponseNorm.size();
	int cols = ResponseNorm.at(0).size();
	CORNER_VEC corner_vec;
	vector<int> vec;
	for (int i = 1; i < rows - 1; i++)
	{
		for (int j = 1; j <cols - 1; j++)
		{   
			
			if ( ResponseNorm.at(i).at(j)  > ResponseNorm.at(i - 1).at(j - 1) &&
				 ResponseNorm.at(i).at(j)  > ResponseNorm.at(i - 1).at(j) &&
				 ResponseNorm.at(i).at(j)  > ResponseNorm.at(i - 1).at(j + 1) &&
				 ResponseNorm.at(i).at(j)  > ResponseNorm.at(i).at(j - 1) &&
				 ResponseNorm.at(i).at(j)  > ResponseNorm.at(i).at(j + 1) &&
				 ResponseNorm.at(i).at(j)  > ResponseNorm.at(i + 1).at(j - 1) &&
				 ResponseNorm.at(i).at(j)  > ResponseNorm.at(i + 1).at(j) &&
				 ResponseNorm.at(i).at(j)  > ResponseNorm.at(i+1).at(j + 1)){
				if (ResponseNorm.at(i).at(j) > 200){
					vec.push_back(i);
					vec.push_back(j);
					corner_vec.push_back(vec);
					vec.clear();
				}
				
			}
			
		}
		
	}
	

	return corner_vec;
}


CORNER_VEC HarrisCornerDetection(IMAGE srcImage) {
	cout << endl;
	cout << "start detecting corners,please wait patiently..." << endl;
	int rows = srcImage.getheight();
	int cols = srcImage.getwidth();
	//DWORD* PTR = GetImageBuffer(&srcImage);
	//定义角点位置向量
	

	IMAGE grayImage = ConvertBGRToGRAY(srcImage);
	IMAGE GX = SobelGradintX(grayImage);
	IMAGE GY = SobelGradintY(grayImage);

	LONG_2DVEC GradXX = SobelXX(GX);
	LONG_2DVEC GradXY = SobelXY(GX,GY);
	LONG_2DVEC GradYY = SobelXX(GY);

	FLOAT_2DVEC Response = HarrisResponse(GradXX, GradXY, GradYY,0.05);
	
    UCHAR_2DVEC ResponseNorm	= DataNormalize( Response);
	CORNER_VEC CORNER_VECTOR = LocalMaxValue(ResponseNorm);
	cout << "detection end." << endl;
	cout << "The number of corners detected is: " << CORNER_VECTOR.size() << endl;
	
   return CORNER_VECTOR;
}

void PaintCorner(CORNER_VEC CORNER_VECTOR,IMAGE srcImage) {
	initgraph(srcImage.getwidth(), srcImage.getheight(), EW_SHOWCONSOLE | EW_NOCLOSE | EW_NOMINIMIZE);
	putimage(0, 0, &srcImage);
	setlinecolor(GREEN);
	for (int i = 0; i < CORNER_VECTOR.size(); i++) {
		circle(CORNER_VECTOR.at(i).at(0), CORNER_VECTOR.at(i).at(1), 10);
	}
	FlushBatchDraw();
}

main.c


#include "harris.h"




int main()
{
	cout << "***************** CORNERS DETECTION *****************" << endl;
	cout << endl;
	cout << endl;
	while (1) {
		cout << "Whether to use the default image(Y/N): ";
		char ch ;
		cin >> ch;
		string filename;
		if (ch == 'Y') {
			filename = "building.jpg";
		}
		else {
			cout << "Please enter a image name: ";
			cin >> filename;
		}
		cout << "The image name is: " << filename << endl;
		
		int length = filename.size();
		wchar_t *lpwsz = new wchar_t[length + 1];
		ConvertStringToWchar(filename, lpwsz);
		IMAGE srcImage;
		loadimage(&srcImage, lpwsz);
		delete[]lpwsz;
		DWORD* SRC_PTR = GetImageBuffer(&srcImage);
		//CORNER_VEC CORNER_VECTOR;
		if (SRC_PTR == NULL) {
			cout << "There are no the image named " << filename << endl;
			cout << "Click any key to continue." << endl;
			cout << endl;
		}
		else{
			int imageHight, imageWidth;
			imageHight = srcImage.getheight();
			imageWidth = srcImage.getwidth();
			IMAGE grayImage = ConvertBGRToGRAY(srcImage);
			initgraph(imageWidth, imageHight, EW_SHOWCONSOLE |EW_NOCLOSE | EW_NOMINIMIZE);
			putimage(0, 0, &srcImage);
			cout << "Click any key to start detecting corners." << endl;
			_getch();
	        CORNER_VEC CORNER_VECTOR = HarrisCornerDetection(srcImage);
			cout << endl;
			cout << "Click any key to paint  corners detected." << endl;
			_getch();
			closegraph();
			IMAGE img = srcImage;
			PaintCorner(CORNER_VECTOR, img);
			cout << endl;
			cout << "Click any key to close window." << endl;
			_getch();
			closegraph();
        }
		cout << endl;
		cout << "End detecting or not(Y/N): ";
		char end;
		cin >> end;
		if (end == 'Y') {
			exit(0);
		}
		cout << endl;
	}
	return 0;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值