Harris算子以及未来的规划...

Harris算子以及未来规划...

找工作的时候,被问到了harris,面试官问梯度矩阵特征值在边缘区域的分布情况。当时答的感觉也没啥问题,但面试官就是在我说出答案后特别诧异.....回来后挺难过.....后来又问了相机标定的流程,我只敢写个相机模型,没怎么答上来相机标定怎么计算。。感觉coding还是不够深入,找到工作后,发现自己很多不足的地方。打算赶紧抢救下。。

1.Harris 实现,这个应该不难。

2.多尺度的harris ,Hessian,DoG,HarrisLaplace,HessianLaplace,看看论文和VLFeat 实现下。

3.相机标定,在看机器人视觉测量与控制这本书,近几天不忙应该能coding一个basic相机标定的算法。

4.再把三大特征看完 HoG,Harr,LBP

4.1看下HDR的论文,实现一下算法过程,此外把scaling 图像缩放看一下

5.项目上面的话,线结构光的可以改进下激光平面标定的算法,用PNP算一下

6.把PNP的视频看完,还有几篇论文。

7.做一下知识管理,找工作后发现好的知识管理和高效率很重要。

8.未来:关注物体检测(FastRCNN和YOLO)人脸识别,以及人脸特征点。以及GIMP的源码。写点linux上跑的图像处理软件。

9.学习层面的话,先把操作系统,算法设计看完,计算机网络也恶补一下,开始入嵌入式操作系统的坑,最好是把安卓移植过程了解清楚,以及安卓的一些坑。

10.再长远的话学java,入安卓的坑了,写一点在安卓上跑的app。

以下是Harris C++源码:

参考过https://github.com/RonnyYoung/ImageFeatures/blob/master/source/harris.cpp

在处理非极大抑制上做的蛮好。

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <math.h>
using namespace std;
using namespace cv;
class CmpHarris
{
public:
	CmpHarris(const Mat& img, int threshold = 0.01, float _lamada = 0.04) : thresh(threshold), lamada(_lamada) {
		if (img.channels() == 3)
		{
			cvtColor(img, image, CV_RGB2GRAY);
			image.convertTo(image, CV_32FC1);
		}
		else
		{
			image = img.clone();
			image.convertTo(image, CV_32FC1);
		}
		gradx2 = cv::Mat::zeros(img.size(), CV_32FC1);
		grady2 = cv::Mat::zeros(img.size(), CV_32FC1);
		gradxy = cv::Mat::zeros(img.size(), CV_32FC1);

	};
	
	void CmpHarris::getHarrisRespose(vector<Point2d> &response,Mat& res);
	~CmpHarris()
	{
		
	}
private:
	Mat image;
	Mat gradx2;
	Mat grady2;
	Mat gradxy;
	float thresh;
	float lamada;
	int cmpSobel(Mat& image, Mat& gardx2, Mat& gardy2, Mat& gardxy);
	int Harris(vector<Point2d> &response,Mat& res, Mat& gradx2, Mat& grady2, Mat & gradxy, float thresh, float lamada);
};
int CmpHarris::cmpSobel(Mat& image, Mat& gardx2, Mat& gardy2, Mat& gradxy)
{
	int width = image.cols;
	int height = image.rows;
	Mat gradX, gradY;
	gradX = Mat::zeros(gradx2.size(), CV_32FC1);
	gradY = Mat::zeros(grady2.size(), CV_32FC1);
	for (int i = 1; i < height - 1; i++)
	{
		float* data = image.ptr<float>(i);
		float* gradxd = gradX.ptr<float>(i);
		float* gradyd = gradY.ptr<float>(i);
		float* updata = image.ptr<float>(i - 1);
		float* downdata = image.ptr<float>(i + 1);
		for (int j = 1; j < width - 1; j++)
		{
			float gradx, grady;
			float a00, a01, a02, a10, a12, a20, a21, a22;
			a00 = updata[j - 1]; a01 = updata[j]; a02 = updata[j + 1];
			a10 = data[j - 1]; a12 = data[j + 1];
			a20 = downdata[j - 1]; a21 = downdata[j]; a22 = downdata[j + 1];
			/*gradx = -a00 - a10 * 2 - a20 + a02 + 2 * a12 + a22;
			grady = -a00 - a01 * 2 - a02 + a20 + 2 * a21 + a22;*/
			gradx = -a00 - a10 * 2 - a20 + a02 + 2 * a12 + a22;
			grady = -a00 - a01 * 2 - a02 + a20 + 2 * a21 + a22;
			gradxd[j] = gradx;
			gradyd[j] = grady;
		}
	}
	gradx2 = gradX.mul(gradX);
	grady2 = gradY.mul(gradY);
	gradxy = gradX.mul(gradY);
	return 1;
}
int CmpHarris::Harris(vector<Point2d> &response,Mat& res, Mat& gradx2, Mat& grady2, Mat & gradxy,float thresh, float lamada)
{
	//首先进行行卷积

	Mat gaussKernel = getGaussianKernel(7, 2);
	Mat HarrisResponse;
	HarrisResponse = Mat::zeros(gradx2.size(),CV_32FC1);
	filter2D(gradx2, gradx2, CV_32FC1, gaussKernel);
	filter2D(grady2, grady2, CV_32FC1, gaussKernel);
	filter2D(gradxy, gradxy, CV_32FC1, gaussKernel);
	for (int i = 0; i < gradx2.rows; i++)
	{
		float* dataRes = HarrisResponse.ptr<float>(i);
		for (int j = 0; j <  gradx2.cols; j++)
		{
			float sumGradx2, sumGrady2, sumGradxy;
			sumGradx2 = sumGrady2 = sumGradxy = 0;
			sumGradx2 = gradx2.at<float>(i, j);
			sumGrady2 = grady2.at<float>(i, j);
			sumGradxy = gradxy.at<float>(i, j);
			float det_m = sumGradx2 *sumGrady2 - sumGradxy  * sumGradxy;
			float trace_m = sumGradx2 + sumGrady2;
			dataRes[j] = det_m - lamada * trace_m * trace_m;
		}
	}
	//NMS + aaaaaaaaaaaaaa
	double maxResponse = 0;
	minMaxLoc(HarrisResponse, NULL, &maxResponse,NULL,NULL);
	Mat dilated;
	Mat localMax;

	//膨胀就是求局部最大值的操作,核B与图形卷积,
	//即计算核B覆盖的区域的像素点的最大值,
	//并把这个最大值赋值给参考点指定的像素
	dilate(HarrisResponse, dilated, Mat());

	compare(HarrisResponse, dilated, localMax, CMP_EQ);

	Mat cornerMap;
	double qualityLevel = 0.01;
	double threshs = qualityLevel * maxResponse;
	cornerMap = HarrisResponse > threshs;
	bitwise_and(cornerMap, localMax, res);
	for (int i = 0; i < res.rows; i++)
	{
		uchar* p = res.ptr<uchar>(i);
		for (int j = 0; j < res.cols; j++)
		{
			if (p[j])
			{
				response.push_back(Point2d(i, j));
			}
		}
	 }
	/*imshow("cv1", dilated);
	imshow("c2", HarrisResponse);
	imshow("cv3", localMax);
	imshow("cv4", res);
	waitKey(0);
	*/

	return 1;
}

void CmpHarris::getHarrisRespose(vector<Point2d> &response,Mat& res)
{
	cmpSobel(this->image, this->gradx2, this->grady2, this->gradxy);
	Harris(response,res, this->gradx2, this->grady2, this->gradxy, this->thresh, this->lamada);
}

int main(int argc, char **argv) {
	cv::Mat im;
	Mat image, res, res_norm, res_norm_scale;
	vector<Point2d> HarrisRespose;
	im = cv::imread("D://2.jpg");
	CmpHarris harris(im, 0.01, 0.04);
	harris.getHarrisRespose(HarrisRespose,res);
	if (!HarrisRespose.empty())
	{
		for (int i = 0; i < HarrisRespose.size(); i++)
		{
			Point FeatPoint(HarrisRespose[i].y, HarrisRespose[i].x);
			circle(im, FeatPoint, 1, CV_RGB(0, 255, 0), 2, 0, 0);
		}
	}
	namedWindow("harris");
	imshow("harris", im);
	waitKey(0);
	return 0;
}

上图是C++版本生成harris角点

下面是matlab版本的:

% in_image-待检测的rgb图像数组
% a--角点参数响应,取值范围:0.04~0.06
% [posr,posc]-角点坐标
in_image = imread('D:\\2.jpg');
a = 0.04;
in_image=rgb2gray(in_image);
I=double(in_image);
%%%%计算xy方向梯度%%%%%

fx=[-1,0,1];%x方向梯度模板
Ix=filter2(fx,I);%x方向滤波
fy=[-1;0;1];%y方向梯度模板(注意是分号)
Iy=filter2(fy,I);
%%%%计算两个方向梯度的乘积%%%%%
Ix2=Ix.^2;
Iy2=Iy.^2;
Ixy=Ix.*Iy;
%%%%使用高斯加权函数对梯度乘积进行加权%%%%
%产生一个7*7的高斯窗函数,sigma值为2
h=fspecial('gaussian',[7,7],2);
IX2=filter2(h,Ix2);
IY2=filter2(h,Iy2);
IXY=filter2(h,Ixy);
%%%%%计算每个像元的Harris响应值%%%%%
[height,width]=size(I);
R=zeros(height,width);
%像素(i,j)处的Harris响应值
for i=1:height
    for j=1:width
        M=[IX2(i,j) IXY(i,j);IXY(i,j) IY2(i,j)];
        R(i,j)=det(M)-a*(trace(M))^2;
    end
end

%%%%%去掉小阈值的Harris值%%%%%
Rmax=max(max(R));
%阈值
t=0.01*Rmax;
for i=1:height
    for j=1:width
        if R(i,j)<t
            R(i,j)=0;
        end
    end
end
figure
imshow(R);
hold on
%%%%%进行3*3领域非极大值抑制%%%%%%%%%
corner_peaks=imregionalmax(R);
%imregionalmax对二维图片,采用8领域(默认,也可指定)查找极值,三维图片采用26领域
%极值置为1,其余置为0
num=sum(sum(corner_peaks));
%%%%%%显示所提取的Harris角点%%%%
[posr,posc]=find(corner_peaks==1);
figure
imshow(in_image);
hold on
for i=1:length(posr)
    plot(posc(i),posr(i),'r+');
end

上图是matlab生成的harris角点

posted @ 2017-09-25 20:57  melo11  阅读(778)  评论(0编辑  收藏  举报
TOP