Harris算子以及將來規劃...java
找工做的時候,被問到了harris,面試官問梯度矩陣特徵值在邊緣區域的分佈狀況。當時答的感受也沒啥問題,但面試官就是在我說出答案後特別詫異.....回來後挺難過.....後來又問了相機標定的流程,我只敢寫個相機模型,沒怎麼答上來相機標定怎麼計算。。感受coding仍是不夠深刻,找到工做後,發現本身不少不足的地方。打算趕忙搶救下。。linux
1.Harris 實現,這個應該不難。ios
2.多尺度的harris ,Hessian,DoG,HarrisLaplace,HessianLaplace,看看論文和VLFeat 實現下。git
3.相機標定,在看機器人視覺測量與控制這本書,近幾天不忙應該能coding一個basic相機標定的算法。github
4.再把三大特徵看完 HoG,Harr,LBP面試
4.1看下HDR的論文,實現一下算法過程,此外把scaling 圖像縮放看一下算法
5.項目上面的話,線結構光的能夠改進下激光平面標定的算法,用PNP算一下數組
6.把PNP的視頻看完,還有幾篇論文。網絡
7.作一下知識管理,找工做後發現好的知識管理和高效率很重要。app
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角點