若該文爲原創文章,未經容許不得轉載
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:http://www.javashuo.com/article/p-wxwjppoc-mo.html
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106926496
各位讀者,知識無窮而人力有窮,要麼改需求,要麼找專業人士,要麼本身研究
紅胖子(紅模仿)的博文大全:開發技術集合(包含Qt實用技術、樹莓派、三維、OpenCV、OpenGL、ffmpeg、OSG、單片機、軟硬結合等等)持續更新中…(點擊傳送門)算法
上一篇:《OpenCV開發筆記(六十四):紅胖子8分鐘帶你深刻了解SURF特徵點(圖文並茂+淺顯易懂+程序源碼)》
下一篇:持續補充中…機器學習
紅胖子,來也!
識別除了傳統的模板匹配以外就是體徵點了,前面介紹了Suft特徵點,還有一個傳統的就會ORB特徵點了。
其實識別的特徵點多種多樣,既能夠本身寫也可使用opencv爲咱們提供的,通常來講根據特徵點的特性和效率,選擇適合咱們場景的特徵就能夠了。
本篇,介紹ORB特徵提取。ide
ORB是ORiented Brief的簡稱,是briedf算法的改進版,於2011年在《ORB:an fficient alternative to SIFT or SURF》中提出。
ORB算法分爲兩部分,分別是特徵點提取和特徵點描述:函數
ORB特徵是將FAST特徵點的檢測方法與BRIEF特徵描述子結合起來,並在它們原來的基礎上作了改進與優化。聽說,ORB算法的速度是sift的100倍,是surf的10倍。學習
該特徵描述子是在特徵點附近隨機選取若干點對,將這些點對的灰度值的大小,組合成一個二進制串,組合成一個二進制傳,並將這個二進制串做爲該特徵點的特徵描述子。
Brief的速度快,可是使用灰度值做爲描述字計算的源頭,毫無疑問會有一些顯而易見的問題:優化
該步可以提取大量的特徵點,可是有很大一部分的特徵點的質量不高。從圖像中選取一點P,以P爲圓心畫一個半徑爲N像素半徑的圓。圓周上若是有連續n個像素點的灰度值比P點的灰度值大或者小,則認爲P爲特徵點。
ui
通俗來講就是使用ID3算法訓練一個決策樹,將特徵點圓周上的16個像素輸入決策樹中,以此來篩選出最優的FAST特徵點。.net
使用非極大值抑制算法去除臨近位置多個特徵點的問題。爲每個特徵點計算出其響應大小。計算方式是特徵點P和其周圍16個特徵點誤差的絕對值和。在比較臨近的特徵點中,保留響應值較大的特徵點,刪除其他的特徵點。code
ORB算法提出使用矩(moment)法來肯定FAST特徵點的方向。也就是說經過矩來計算特徵點以r爲半徑範圍內的質心,特徵點座標到質心造成一個向量做爲該特徵點的方向。orm
cv::Ptr<cv::ORB> _pOrb = cv::ORB::create(); std::vector<cv::KeyPoint> keyPoints1; //特徵點檢測 _pOrb->detect(srcMat, keyPoints1);
static Ptr<ORB> create(int nfeatures=500, float scaleFactor=1.2f, int nlevels=8, int edgeThreshold=31, int firstLevel=0, int WTA_K=2, int scoreType=ORB::HARRIS_SCORE, int patchSize=31, int fastThreshold=20);
void xfeatures2d::SURT::detect( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() );
void xfeatures2d::SURT::compute( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors );
// 該函數結合了detect和compute,參照detect和compute函數參數 void xfeatures2d::SURT::detectAndCompute( InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints, OutputArray descriptors, bool useProvidedKeypoints=false );
void drawKeypoints( InputArray image, const std::vector<KeyPoint>& keypoints, InputOutputArray outImage, const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );
本源碼中包含了「透視變換」,請參照博文《OpenCV開發筆記(五十一):紅胖子8分鐘帶你深刻了解透視變換(圖文並茂+淺顯易懂+程序源碼)》
根據前面連續三篇的特徵點,咱們其實能夠猜到了全部的匹配都是這樣提取特徵點,而後使用一些算法來匹配,至於使用什麼特徵點提取就是須要開發者根據實際的經驗去選取,單一的特徵點/多種特徵點提取混合/本身寫特徵點等等多種方式去提取特徵點,爲後一步的特徵點匹配作準備,特徵點通用的就到此篇,後續會根據實際開發項目中使用的到隨時以新的篇章博文去補充。
《OpenCV開發筆記(六十三):紅胖子8分鐘帶你深刻了解SIFT特徵點(圖文並茂+淺顯易懂+程序源碼)》
《OpenCV開發筆記(六十四):紅胖子8分鐘帶你深刻了解SURF特徵點(圖文並茂+淺顯易懂+程序源碼》
《OpenCV開發筆記(六十五):紅胖子8分鐘帶你深刻了解ORB特徵點(圖文並茂+淺顯易懂+程序源碼)》
void OpenCVManager::testOrbFeatureDetector() { QString fileName1 = "13.jpg"; int width = 400; int height = 300; cv::Mat srcMat = cv::imread(fileName1.toStdString()); cv::resize(srcMat, srcMat, cv::Size(width, height)); cv::String windowName = _windowTitle.toStdString(); cvui::init(windowName); cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2, srcMat.rows * 3), srcMat.type()); cv::Ptr<cv::ORB> _pObr = cv::ORB::create(); int k1x = 0; int k1y = 0; int k2x = 100; int k2y = 0; int k3x = 100; int k3y = 100; int k4x = 0; int k4y = 100; while(true) { windowMat = cv::Scalar(0, 0, 0); cv::Mat mat; // 原圖先copy到左邊 mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2), cv::Range(srcMat.cols * 0, srcMat.cols * 1)); cv::addWeighted(mat, 0.0f, srcMat, 1.0f, 0.0f, mat); { std::vector<cv::KeyPoint> keyPoints1; std::vector<cv::KeyPoint> keyPoints2; cvui::printf(windowMat, 0 + width * 1, 10 + height * 0, "k1x"); cvui::trackbar(windowMat, 0 + width * 1, 20 + height * 0, 165, &k1x, 0, 100); cvui::printf(windowMat, 0 + width * 1, 70 + height * 0, "k1y"); cvui::trackbar(windowMat, 0 + width * 1, 80 + height * 0, 165, &k1y, 0, 100); cvui::printf(windowMat, width / 2 + width * 1, 10 + height * 0, "k2x"); cvui::trackbar(windowMat, width / 2 + width * 1, 20 + height * 0, 165, &k2x, 0, 100); cvui::printf(windowMat, width / 2 + width * 1, 70 + height * 0, "k2y"); cvui::trackbar(windowMat, width / 2 + width * 1, 80 + height * 0, 165, &k2y, 0, 100); cvui::printf(windowMat, 0 + width * 1, 10 + height * 0 + height / 2, "k3x"); cvui::trackbar(windowMat, 0 + width * 1, 20 + height * 0 + height / 2, 165, &k3x, 0, 100); cvui::printf(windowMat, 0 + width * 1, 70 + height * 0 + height / 2, "k3y"); cvui::trackbar(windowMat, 0 + width * 1, 80 + height * 0 + height / 2, 165, &k3y, 0, 100); cvui::printf(windowMat, width / 2 + width * 1, 10 + height * 0 + height / 2, "k4x"); cvui::trackbar(windowMat, width / 2 + width * 1, 20 + height * 0 + height / 2, 165, &k4x, 0, 100); cvui::printf(windowMat, width / 2 + width * 1, 70 + height * 0 + height / 2, "k4y"); cvui::trackbar(windowMat, width / 2 + width * 1, 80 + height * 0 + height / 2, 165, &k4y, 0, 100); std::vector<cv::Point2f> srcPoints; std::vector<cv::Point2f> dstPoints; srcPoints.push_back(cv::Point2f(0.0f, 0.0f)); srcPoints.push_back(cv::Point2f(srcMat.cols - 1, 0.0f)); srcPoints.push_back(cv::Point2f(srcMat.cols - 1, srcMat.rows - 1)); srcPoints.push_back(cv::Point2f(0.0f, srcMat.rows - 1)); dstPoints.push_back(cv::Point2f(srcMat.cols * k1x / 100.0f, srcMat.rows * k1y / 100.0f)); dstPoints.push_back(cv::Point2f(srcMat.cols * k2x / 100.0f, srcMat.rows * k2y / 100.0f)); dstPoints.push_back(cv::Point2f(srcMat.cols * k3x / 100.0f, srcMat.rows * k3y / 100.0f)); dstPoints.push_back(cv::Point2f(srcMat.cols * k4x / 100.0f, srcMat.rows * k4y / 100.0f)); cv::Mat M = cv::getPerspectiveTransform(srcPoints, dstPoints); cv::Mat srcMat2; cv::warpPerspective(srcMat, srcMat2, M, cv::Size(srcMat.cols, srcMat.rows), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(0)); mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2), cv::Range(srcMat.cols * 1, srcMat.cols * 2)); cv::addWeighted(mat, 0.0f, srcMat2, 1.0f, 0.0f, mat); //特徵點檢測 _pObr->detect(srcMat, keyPoints1); //繪製特徵點(關鍵點) cv::Mat resultShowMat; cv::drawKeypoints(srcMat, keyPoints1, resultShowMat, cv::Scalar(0, 0, 255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3), cv::Range(srcMat.cols * 0, srcMat.cols * 1)); cv::addWeighted(mat, 0.0f, resultShowMat, 1.0f, 0.0f, mat); //特徵點檢測 _pObr->detect(srcMat2, keyPoints2); //繪製特徵點(關鍵點) cv::Mat resultShowMat2; cv::drawKeypoints(srcMat2, keyPoints2, resultShowMat2, cv::Scalar(0, 0, 255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3), cv::Range(srcMat.cols * 1, srcMat.cols * 2)); cv::addWeighted(mat, 0.0f, resultShowMat2, 1.0f, 0.0f, mat); cv::imshow(windowName, windowMat); } // 更新 cvui::update(); // 顯示 // esc鍵退出 if(cv::waitKey(25) == 27) { break; } } }
對應版本號v1.59.0
上一篇:《OpenCV開發筆記(六十四):紅胖子8分鐘帶你深刻了解SURF特徵點(圖文並茂+淺顯易懂+程序源碼)》
下一篇:持續補充中…