日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Harris及Shi-Tomasi原理及源码解析

發布時間:2025/7/25 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Harris及Shi-Tomasi原理及源码解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文采用的是opencv2.4.3中的源碼。

轉載請注明出處:http://blog.csdn.net/luoshixian099/article/details/48244255

CSDN-勿在浮沙筑高臺

Harris角點檢測

? ?人眼對角點的識別通常是通過一個局部的小窗口內完成的,如果在各個方向上移動這個小窗口,窗口內的灰度發生了較大的變化,那么說明窗口內存在角點。

? 如果在各個方向移動,灰度幾乎不變,說明是平坦區域;

? 如果只沿著某一個方向移動,灰度幾乎不變,說明是直線;

? 如果沿各個方向移動,灰度均發生變化,說明是角點。

?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??平坦區域 ??? ? ? ? ? ? ? ? ? ? ? ? ? ?直線??? ? ? ? ? ? ? ? ? ? ? ? ? ? ?角點 ? ? ? ? ? ? ?

圖像I(x,y),在點(x,y)處平移(u,v)后的自相似性,可以用灰度變化函數E(u,v)表示

??

? ? ? ? ? ? ? ? ??

泰勒展開:

代入得到:

? ? ? ? ? ? ? ? ? ? ? ??

其中:

? ? ? ? ? ? ? ? ? ? ? ? ?

二次項函數本質上就是一個橢圓函數,橢圓的扁平率和尺寸是由矩陣M的兩個特征值決定的。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

矩陣M的兩個特征值與圖像中的角點,邊緣,平坦區域的關系:


Harris定義角點響應函數即,即R=Det(M)-k*trace(M)*trace(M)k為經驗常數0.04~0.06 。

定義當R>threshold時且為局部極大值的點時,定義為角點。

Harris角點檢測算子對圖像亮度和對比度具有部分不變性,且具有旋轉不變性,但不具有尺度不變性。

? ? ? ? ? ? ? ? ? ? ? ? ? ?

opencv中調用cornerHarris函數檢測角點:

blockSize:為鄰域大小,對每個像素,考慮blockSize×blockSize大小的鄰域S(p),在鄰域上計算圖像的差分的相關矩陣;


ksize: 為Soble算子核尺寸,如果小于0,采用3×3的Scharr濾波器;

k:為角點響應函數中的經驗常數(0.04~0.06);

[cpp]?view plaincopy print?
  • int?blockSize?=?2;??
  • int?apertureSize?=3;??
  • double?k?=?0.04;??
  • ///?Detecting?corners??
  • cornerHarris(?src_gray,?dst,?blockSize,?apertureSize,?k,?BORDER_DEFAULT?);???
  • [cpp]?view plaincopy print?
  • void?cv::cornerHarris(?InputArray?_src,?OutputArray?_dst,?int?blockSize,?int?ksize,?double?k,?int?borderType?)??
  • {??
  • ????Mat?src?=?_src.getMat();??
  • ????_dst.create(?src.size(),?CV_32F?);??
  • ????Mat?dst?=?_dst.getMat();??
  • ????cornerEigenValsVecs(?src,?dst,?blockSize,?ksize,?HARRIS,?k,?borderType?);//調用函數計算圖像塊的特征值和特征向量??
  • }??
  • [cpp]?view plaincopy print?
  • static?void??
  • cornerEigenValsVecs(?const?Mat&?src,?Mat&?eigenv,?int?block_size,??
  • ?????????????????????int?aperture_size,?int?op_type,?double?k=0.,??
  • ?????????????????????int?borderType=BORDER_DEFAULT?)??
  • {??
  • #ifdef?HAVE_TEGRA_OPTIMIZATION??
  • ????if?(tegra::cornerEigenValsVecs(src,?eigenv,?block_size,?aperture_size,?op_type,?k,?borderType))??
  • ????????return;??
  • #endif??
  • ??
  • ??
  • ????int?depth?=?src.depth();??
  • ????double?scale?=?(double)(1?<<?((aperture_size?>?0???aperture_size?:?3)?-?1))?*?block_size;??
  • ????if(?aperture_size?<?0?)??
  • ????????scale?*=?2.;??
  • ????if(?depth?==?CV_8U?)??
  • ????????scale?*=?255.;??
  • ????scale?=?1./scale;??
  • ????CV_Assert(?src.type()?==?CV_8UC1?||?src.type()?==?CV_32FC1?);??
  • ??
  • ??
  • ????Mat?Dx,?Dy;???//保存每個像素點的水平方向和垂直方向的一階差分??
  • ????if(?aperture_size?>?0?)//采用Sobel濾波器??
  • ????{??
  • ????????Sobel(?src,?Dx,?CV_32F,?1,?0,?aperture_size,?scale,?0,?borderType?);??
  • ????????Sobel(?src,?Dy,?CV_32F,?0,?1,?aperture_size,?scale,?0,?borderType?);??
  • ????}??
  • ????else????//采用3×3的Scharr濾波器,可以給出比3×3?Sobel濾波器更精確的結果??
  • ????{??
  • ????????Scharr(?src,?Dx,?CV_32F,?1,?0,?scale,?0,?borderType?);??
  • ????????Scharr(?src,?Dy,?CV_32F,?0,?1,?scale,?0,?borderType?);??
  • ????}??
  • ??
  • ??
  • ????Size?size?=?src.size();??
  • ????Mat?cov(?size,?CV_32FC3?);??
  • ????int?i,?j;??
  • ??
  • ??
  • ????for(?i?=?0;?i?<?size.height;?i++?)??
  • ????{??
  • ????????float*?cov_data?=?(float*)(cov.data?+?i*cov.step);??
  • ????????const?float*?dxdata?=?(const?float*)(Dx.data?+?i*Dx.step);??
  • ????????const?float*?dydata?=?(const?float*)(Dy.data?+?i*Dy.step);??
  • ??
  • ??
  • ????????for(?j?=?0;?j?<?size.width;?j++?)??
  • ????????{??
  • ????????????float?dx?=?dxdata[j];??
  • ????????????float?dy?=?dydata[j];??
  • ??
  • ??
  • ????????????cov_data[j*3]?=?dx*dx;??//第一個通道存dx*dx,即M矩陣左上角的元素??
  • ????????????cov_data[j*3+1]?=?dx*dy;//第二個通道存dx*dy,即M矩陣左下角和右上角的元素??
  • ????????????cov_data[j*3+2]?=?dy*dy;//第三個通道存dy*dy,即M矩陣右下角的元素??
  • ????????}??
  • ????}??
  • ??
  • ??
  • ????boxFilter(cov,?cov,?cov.depth(),?Size(block_size,?block_size),?//計算鄰域上的差分相關矩陣(block_size×block_size)??
  • ????????Point(-1,-1),?false,?borderType?);??
  • ??
  • ??
  • ????if(?op_type?==?MINEIGENVAL?)???//計算M矩陣的最小的特征值??
  • ????????calcMinEigenVal(?cov,?eigenv?);??
  • ????else?if(?op_type?==?HARRIS?)//計算Harris角點響應函數R??
  • ????????calcHarris(?cov,?eigenv,?k?);??
  • ????else?if(?op_type?==?EIGENVALSVECS?)//計算圖像塊的特征值和特征向量??
  • ????????calcEigenValsVecs(?cov,?eigenv?);??
  • }??
  • [cpp]?view plaincopy print?
  • static?void??
  • calcHarris(?const?Mat&?_cov,?Mat&?_dst,?double?k?)??
  • {??
  • ????int?i,?j;??
  • ????Size?size?=?_cov.size();??
  • ????if(?_cov.isContinuous()?&&?_dst.isContinuous()?)??
  • ????{??
  • ????????size.width?*=?size.height;??
  • ????????size.height?=?1;??
  • ????}??
  • ??
  • ????for(?i?=?0;?i?<?size.height;?i++?)??
  • ????{??
  • ????????const?float*?cov?=?(const?float*)(_cov.data?+?_cov.step*i);??
  • ????????float*?dst?=?(float*)(_dst.data?+?_dst.step*i);??
  • ????????j?=?0;??
  • ????????for(?;?j?<?size.width;?j++?)??
  • ????????{??
  • ????????????float?a?=?cov[j*3];??
  • ????????????float?b?=?cov[j*3+1];??
  • ????????????float?c?=?cov[j*3+2];??
  • ????????????dst[j]?=?(float)(a*c?-?b*b?-?k*(a?+?c)*(a?+?c));??//計算每個像素對應角點響應函數R??
  • ????????}??
  • ????}??
  • }??
  • Shi-Tomasi角點檢測

    由于Harris算法的穩定性和k值有關,Shi-Tomasi發現,角點的穩定性和矩陣M的較小特征值有關,改進的Harris算法即直接計算出矩陣M的特征值,用較小的特征值與閾值比較,大于閾值的即為強特征點。 ? ? ? ? ? ? ? ? ? ? ? ?
    opencv中對其實現算法在goodFeaturesToTrack()函數中: [cpp]?view plaincopy print?
  • CV_EXPORTS_W?void?goodFeaturesToTrack(?InputArray?image,?OutputArray?corners,??
  • ?????????????????????????????????????int?maxCorners,?double?qualityLevel,?double?minDistance,??
  • ?????????????????????????????????????InputArray?mask=noArray(),?int?blockSize=3,??
  • ?????????????????????????????????????bool?useHarrisDetector=false,?double?k=0.04?);??
  • image:輸入圖像 corners:輸出圖像數組 maxCorners:需要的角點數目 qualityLevel:最大,最小特征值的乘法因子。定義可接受圖像角點的最小質量因子。 minDistance:容忍距離。角點之間的最小距離,采用歐氏距離。 mask:掩碼 blockSize:鄰域大小 useHarrisDetector:采用Harris角點檢測 k:采用Harris角點檢測時的經驗常數k(0.04~0.06) 算法原理:調用cornerMinEigenVal()函數求出每個像素點自適應矩陣M的較小特征值,保存在矩陣eig中,然后找到矩陣eig中最大的像素值記為maxVal,然后閾值處理,小于qualityLevel*maxVal的特征值排除掉,最后函數確保所有發現的角點之間具有足夠的距離。
    [cpp]?view plaincopy print?
  • void?cv::goodFeaturesToTrack(?InputArray?_image,?OutputArray?_corners,??
  • ??????????????????????????????int?maxCorners,?double?qualityLevel,?double?minDistance,??
  • ??????????????????????????????InputArray?_mask,?int?blockSize,??
  • ??????????????????????????????bool?useHarrisDetector,?double?harrisK?)??
  • {??
  • ????Mat?image?=?_image.getMat(),?mask?=?_mask.getMat();??
  • ??
  • ????CV_Assert(?qualityLevel?>?0?&&?minDistance?>=?0?&&?maxCorners?>=?0?);??
  • ????CV_Assert(?mask.empty()?||?(mask.type()?==?CV_8UC1?&&?mask.size()?==?image.size())?);??
  • ??
  • ????Mat?eig,?tmp;??
  • ????if(?useHarrisDetector?)???????
  • ????????cornerHarris(?image,?eig,?blockSize,?3,?harrisK?);??//采用Harris角點檢測??
  • ????else??
  • ????????cornerMinEigenVal(?image,?eig,?blockSize,?3?);??//采用Harris改進算法,eig保存矩陣M較小的特征值。見下面算法實現??
  • ??
  • ????double?maxVal?=?0;??
  • ????minMaxLoc(?eig,?0,?&maxVal,?0,?0,?mask?);//保存eig中最大的值maxVal??
  • ????threshold(?eig,?eig,?maxVal*qualityLevel,?0,?THRESH_TOZERO?);//閾值處理,小于maxVal*qualityLevel的像素值歸為0。??
  • ????dilate(?eig,?tmp,?Mat());//膨脹,3×3的核,為了取局部極大值??
  • ??
  • ????Size?imgsize?=?image.size();??
  • ??
  • ????vector<const?float*>?tmpCorners;??
  • ??
  • ????//?collect?list?of?pointers?to?features?-?put?them?into?temporary?image??
  • ????for(?int?y?=?1;?y?<?imgsize.height?-?1;?y++?)??
  • ????{??
  • ????????const?float*?eig_data?=?(const?float*)eig.ptr(y);??
  • ????????const?float*?tmp_data?=?(const?float*)tmp.ptr(y);??
  • ????????const?uchar*?mask_data?=?mask.data???mask.ptr(y)?:?0;??
  • ??
  • ????????for(?int?x?=?1;?x?<?imgsize.width?-?1;?x++?)??
  • ????????{??
  • ????????????float?val?=?eig_data[x];??
  • ????????????if(?val?!=?0?&&?val?==?tmp_data[x]?&&?(!mask_data?||?mask_data[x])?)//局部極大值??
  • ????????????????tmpCorners.push_back(eig_data?+?x);??
  • ????????}??
  • ????}??
  • ??
  • ????sort(?tmpCorners,?greaterThanPtr<float>()?);??//按值從大到小排序??
  • ????vector<Point2f>?corners;??
  • ????size_t?i,?j,?total?=?tmpCorners.size(),?ncorners?=?0;??
  • ?/*???
  • ??網格處理,即把圖像劃分成正方形網格,每個網格邊長為容忍距離minDistance?
  • ??以一個角點位置為中心,minDistance為半徑的區域內部不允許出現第二個角點?
  • ?*/??
  • ????if(minDistance?>=?1)??
  • ????{??
  • ?????????//?Partition?the?image?into?larger?grids??
  • ????????int?w?=?image.cols;??
  • ????????int?h?=?image.rows;??
  • ??????????
  • ????????const?int?cell_size?=?cvRound(minDistance);//劃分成網格,網格邊長為容忍距離??
  • ????????const?int?grid_width?=?(w?+?cell_size?-?1)?/?cell_size;??
  • ????????const?int?grid_height?=?(h?+?cell_size?-?1)?/?cell_size;??
  • ??
  • ????????std::vector<std::vector<Point2f>?>?grid(grid_width*grid_height);??
  • ??
  • ????????minDistance?*=?minDistance;??
  • ??
  • ????????for(?i?=?0;?i?<?total;?i++?)??//按從大到小的順序,遍歷所有角點??
  • ????????{??
  • ????????????int?ofs?=?(int)((const?uchar*)tmpCorners[i]?-?eig.data);??
  • ????????????int?y?=?(int)(ofs?/?eig.step);??
  • ????????????int?x?=?(int)((ofs?-?y*eig.step)/sizeof(float));??
  • ??
  • ????????????bool?good?=?true;??
  • ??
  • ????????????int?x_cell?=?x?/?cell_size;??
  • ????????????int?y_cell?=?y?/?cell_size;??
  • ??
  • ????????????int?x1?=?x_cell?-?1;??
  • ????????????int?y1?=?y_cell?-?1;??
  • ????????????int?x2?=?x_cell?+?1;??
  • ????????????int?y2?=?y_cell?+?1;??
  • ??
  • ????????????//?boundary?check??
  • ????????????x1?=?std::max(0,?x1);??
  • ????????????y1?=?std::max(0,?y1);??
  • ????????????x2?=?std::min(grid_width-1,?x2);??
  • ????????????y2?=?std::min(grid_height-1,?y2);??
  • ??
  • ????????????for(?int?yy?=?y1;?yy?<=?y2;?yy++?)//檢測角點,minDistance半徑鄰域內,有沒有其他角點出現??
  • ????????????{??
  • ????????????????for(?int?xx?=?x1;?xx?<=?x2;?xx++?)??
  • ????????????????{??
  • ????????????????????vector?<Point2f>?&m?=?grid[yy*grid_width?+?xx];??
  • ??
  • ????????????????????if(?m.size()?)??
  • ????????????????????{??
  • ????????????????????????for(j?=?0;?j?<?m.size();?j++)??
  • ????????????????????????{??
  • ????????????????????????????float?dx?=?x?-?m[j].x;??
  • ????????????????????????????float?dy?=?y?-?m[j].y;??
  • ????????????????????????????if(?dx*dx?+?dy*dy?<?minDistance?)//有其他角點,丟棄當前角點??
  • ????????????????????????????{??
  • ????????????????????????????????good?=?false;??
  • ????????????????????????????????goto?break_out;??
  • ????????????????????????????}??
  • ????????????????????????}??
  • ????????????????????}??
  • ????????????????}??
  • ????????????}??
  • ??
  • ????????????break_out:??
  • ??
  • ????????????if(good)??
  • ????????????{??
  • ????????????????//?printf("%d:?%d?%d?->?%d?%d,?%d,?%d?--?%d?%d?%d?%d,?%d?%d,?c=%d\n",??
  • ????????????????//????i,x,?y,?x_cell,?y_cell,?(int)minDistance,?cell_size,x1,y1,x2,y2,?grid_width,grid_height,c);??
  • ????????????????grid[y_cell*grid_width?+?x_cell].push_back(Point2f((float)x,?(float)y));??
  • ??
  • ????????????????corners.push_back(Point2f((float)x,?(float)y));//滿足條件的存入corners??
  • ????????????????++ncorners;??
  • ??
  • ????????????????if(?maxCorners?>?0?&&?(int)ncorners?==?maxCorners?)??
  • ????????????????????break;??
  • ????????????}??
  • ????????}??
  • ????}??
  • ????else???//不設置容忍距離??
  • ????{??
  • ????????for(?i?=?0;?i?<?total;?i++?)??
  • ????????{??
  • ????????????int?ofs?=?(int)((const?uchar*)tmpCorners[i]?-?eig.data);??
  • ????????????int?y?=?(int)(ofs?/?eig.step);??
  • ????????????int?x?=?(int)((ofs?-?y*eig.step)/sizeof(float));??
  • ??
  • ????????????corners.push_back(Point2f((float)x,?(float)y));??
  • ????????????++ncorners;??
  • ????????????if(?maxCorners?>?0?&&?(int)ncorners?==?maxCorners?)??
  • ????????????????break;??
  • ????????}??
  • ????}??
  • ??
  • ????Mat(corners).convertTo(_corners,?_corners.fixedType()???_corners.type()?:?CV_32F);??
  • ??
  • }??
  • 求矩陣M最小的特征值


    [cpp]?view plaincopy print?
  • static?void??
  • calcMinEigenVal(?const?Mat&?_cov,?Mat&?_dst?)??
  • {??
  • ????int?i,?j;??
  • ????Size?size?=?_cov.size();??
  • ????if(?_cov.isContinuous()?&&?_dst.isContinuous()?)??
  • ????{??
  • ????????size.width?*=?size.height;??
  • ????????size.height?=?1;??
  • ????}??
  • ??
  • ????for(?i?=?0;?i?<?size.height;?i++?)//遍歷所有像素點??
  • ????{??
  • ????????const?float*?cov?=?(const?float*)(_cov.data?+?_cov.step*i);??
  • ????????float*?dst?=?(float*)(_dst.data?+?_dst.step*i);??
  • ????????j?=?0;??
  • ????????for(?;?j?<?size.width;?j++?)??
  • ????????{??
  • ????????????float?a?=?cov[j*3]*0.5f;//cov[j*3]保存矩陣M左上角元素??
  • ????????????float?b?=?cov[j*3+1];???//cov[j*3+1]保存左下角和右上角元素??
  • ????????????float?c?=?cov[j*3+2]*0.5f;//cov[j*3+2]右下角元素??
  • ????????????dst[j]?=?(float)((a?+?c)?-?std::sqrt((a?-?c)*(a?-?c)?+?b*b));//求最小特征值,一元二次方程求根公式??
  • ????????}??
  • ????}??
  • }??
  • 參考:http://blog.csdn.net/xw20084898/article/details/21180729

    ? ? ? ? ?http://wenku.baidu.com/view/f61bc369561252d380eb6ef0.html

    ? ? ? ? ?http://blog.csdn.net/crzy_sparrow/article/details/7391511? ???

    總結

    以上是生活随笔為你收集整理的Harris及Shi-Tomasi原理及源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。