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角點


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com