目錄
1、Shi-Tomas角點(diǎn)檢測(cè)
2、亞像素級(jí)別角點(diǎn)位置優(yōu)化
3、ORB特征點(diǎn)
4、特征點(diǎn)匹配
5、RANSAC優(yōu)化特征點(diǎn)匹配
6、相機(jī)模型與投影
1、Shi-Tomas角點(diǎn)檢測(cè)
?
//Shi-Tomas角點(diǎn)檢測(cè)
int test1()
{
Mat img = imread("F:/testMap/lena.png");
if (!img.data)
{
cout << "讀取圖像錯(cuò)誤, 請(qǐng)確認(rèn)圖像文件是否正確" << endl;
return -1;
}
Mat gray;
cvtColor(img, gray,COLOR_BGR2GRAY);
//Detector parametersl
//提取角點(diǎn)
int maxCorners = 100;//檢測(cè)角點(diǎn)數(shù)目
double quality_level = 0.01;//質(zhì)量等級(jí),或者說(shuō)閾值與最佳角點(diǎn)的比例關(guān)系
double minDistance = 0.04;//兩個(gè)角點(diǎn)之間的最小歐式距離
vector<Point2f> corners;
goodFeaturesToTrack(gray,corners,maxCorners,quality_level, minDistance,Mat(),3,false);
//繪制角點(diǎn)
vector<KeyPoint> keyPoints;//存放角點(diǎn)的KeyPoint類,用于后期繪制角點(diǎn)時(shí)用
for (int i = 0; i < corners.size(); i++)
{
//將角點(diǎn)存放在KeyPoint類中
KeyPoint keyPoint;
keyPoint.pt = corners[i];
keyPoints.push_back(keyPoint);
}
//用drawKeypoints()函數(shù)繪制角點(diǎn)坐標(biāo)
drawKeypoints(img, keyPoints, img);
imshow("角點(diǎn)結(jié)果", img);
waitKey(0);
return 0;
}
?2、亞像素級(jí)別角點(diǎn)位置優(yōu)化
?
//亞像素級(jí)別角點(diǎn)位置優(yōu)化
int test2()
{
system("color 02");//改變DOS界面顏色
Mat img = imread("F:/testMap/lena.png", IMREAD_COLOR);
if (!img.data)
{
cout << "讀取圖像錯(cuò)誤,請(qǐng)確認(rèn)圖像文件是否正確" << endl;
return -1;
}
//彩色圖像轉(zhuǎn)成灰度圖像
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
//提取角點(diǎn)
int maxCorners = 100;//檢測(cè)角點(diǎn)數(shù)目
double quality_level = 0.01;//質(zhì)量等級(jí),或者說(shuō)閾值與最佳角點(diǎn)的比例關(guān)系
double minDistance = 0.04;//兩個(gè)角點(diǎn)之間的最小歐式距離
vector<Point2f> corners;
goodFeaturesToTrack(gray, corners, maxCorners, quality_level, minDistance, Mat(), 3, false);
//計(jì)算亞像素級(jí)別角點(diǎn)坐標(biāo)
vector<Point2f> cornersSub = corners;//角點(diǎn)備份,防止被函數(shù)修改
Size winSize = Size(5, 5);
Size zeroZone = Size(-1, -1);
TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 40, 0.001);
cornerSubPix(gray, cornersSub, winSize, zeroZone, criteria);
//輸出初始坐標(biāo)和精細(xì)坐標(biāo)
for (size_t i = 0; i < corners.size(); i++)
{
string str = to_string(i);
str = "第" + str + "個(gè)角點(diǎn)點(diǎn)初始坐標(biāo):";
cout << str << corners[i] << "精細(xì)后坐標(biāo):" << cornersSub[i] << endl;
}
waitKey(0);
return 0;
}
3、ORB特征點(diǎn)
?
?
?
//ORB特征點(diǎn)
int test3()
{
Mat img = imread("F:/testMap/lena.png");
if (!img.data)
{
cout << "請(qǐng)確認(rèn)圖像文件名稱是否正確" << endl;
return -1;
}
//創(chuàng)建ORB特征點(diǎn)類變量
Ptr<ORB> orb = ORB::create(500,//特征點(diǎn)數(shù)目
1.2f,//金字塔層級(jí)之間的縮放比例
8,//金字塔圖像層數(shù)系數(shù)
31,//邊緣閾值
0,//原圖在金字塔中的層數(shù)
2,//生成描述子時(shí)需要用的像素點(diǎn)數(shù)目
ORB::HARRIS_SCORE,//使用 Harris方法評(píng)價(jià)特征點(diǎn)
31,//生成描述子時(shí)關(guān)鍵點(diǎn)周?chē)徲虻某叽? 20//計(jì)算 FAST角點(diǎn)時(shí)像素值差值的閾值
);
//計(jì)算ORB關(guān)鍵點(diǎn)
vector<KeyPoint> Keypoints;
orb->detect(img, Keypoints);//確定關(guān)鍵點(diǎn)
//計(jì)算ORB描述子
Mat descriptions;
orb->compute(img, Keypoints, descriptions);//計(jì)算描述子
//繪制特征點(diǎn)
Mat imgAngel;
img.copyTo(imgAngel);
//繪制不含角度和大小的結(jié)果
drawKeypoints(img, Keypoints, img, Scalar(255, 255, 255));//繪制含有角度和大小的結(jié)果
drawKeypoints(img, Keypoints, imgAngel, Scalar(255, 255, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
//顯示結(jié)果
imshow("不含角度和大小的結(jié)果", img);
imshow("含有角度和大小的結(jié)果", imgAngel);
waitKey(0);
return 0;
}
4、特征點(diǎn)匹配
?
?
//特征點(diǎn)匹配
void orb_features(Mat &gray,vector<KeyPoint> &keypionts,Mat &descriptions)
{
Ptr<ORB> orb = ORB::create(1000,1.2f);
orb->detect(gray,keypionts);
orb->compute(gray,keypionts,descriptions);
}
int test1()
{
Mat img1, img2;
img1 = imread("F:/testMap/box.png");
img2 = imread("F:/testMap/box_in_scen.png");
if (!(img1.data && img2.dataend))
{
cout << "讀取圖像錯(cuò)誤,請(qǐng)確認(rèn)圖像文件是否正確" << endl;
return -1;
}
//提取ORB特征點(diǎn)
vector<KeyPoint> Keypoints1, Keypoints2;
Mat descriptions1, descriptions2;
//計(jì)算特征點(diǎn)
orb_features(img1, Keypoints1, descriptions1);
orb_features(img2, Keypoints2, descriptions2);
//特征點(diǎn)匹配
vector<DMatch> matches;//定義存放匹配結(jié)果的變最
BFMatcher matcher(NORM_HAMMING);//定義特征點(diǎn)匹配的類,使用漢明距離
matcher.match(descriptions1, descriptions2, matches);//進(jìn)行特征點(diǎn)匹配
cout << "matches=" << matches.size() << endl;//匹配成功特征點(diǎn)數(shù)目
//通過(guò)漢明距離刪選匹配結(jié)果
double min_dist = 0, max_dist = 10000;
for (int i = 0; i < matches.size(); i++)
{
double dist = matches[i].distance;
if (dist < min_dist) min_dist = dist;
if (dist > max_dist) max_dist = dist;
}
//輸出所有匹配結(jié)果中最大韓明距離和最小漢明距離
cout << "min_dist=" << min_dist << endl;
cout << "max_dist=" << max_dist << endl;
//將漢明距離較大的匹配點(diǎn)對(duì)刪除
vector<DMatch>good_matches;
for (int i = 0; i < matches.size(); i++)
{
if (matches[i].distance <= max(2 * min_dist, 20.0))
{
good_matches.push_back(matches[i]);
}
}
cout << "good_min=" << good_matches.size() << endl;//剩余特征點(diǎn)數(shù)目
//繪制匹配結(jié)果
Mat outimg, outimg1;
drawMatches(img1, Keypoints1, img2, Keypoints2, matches, outimg);
drawMatches(img1, Keypoints1, img2, Keypoints2, good_matches, outimg1);
imshow("未篩選結(jié)果", outimg);
imshow("最小漢明距離篩選", outimg1);
waitKey(0);
return 0;
}
5、RANSAC優(yōu)化特征點(diǎn)匹配
?
?
void match_min(vector<DMatch> matches, vector<DMatch> & good_matches)//最小漢明距離
{
double min_dist = 10000, max_dist = 0;
for (int i = 0; i < matches.size(); i++)
{
double dist = matches[i].distance;
if (dist < min_dist) min_dist = dist;
if (dist > max_dist) max_dist = dist;
}
cout << "min_dist=" << min_dist << endl;
cout << "max_dist=" << max_dist << endl;
for (int i = 0; i < matches.size(); i++)
{
if (matches[i].distance <= max(2 * min_dist, 20.0))
{
good_matches.push_back(matches[i]);
}
}
}
//RANSAC算法實(shí)現(xiàn)
void ransac(vector<DMatch>matches, vector <KeyPoint> queryifeyPoint, vector<KeyPoint> trainieyPoint, vector<DMatch> &kmatches_ransac)
{
//定義保存匹配點(diǎn)對(duì)坐標(biāo)
vector<Point2f> srcPoints(matches.size()), dstPoints(matches.size());
//保存從關(guān)鍵點(diǎn)中提取到的匹配點(diǎn)對(duì)的坐標(biāo)
for (int i = 0; i < matches.size(); i++)
{
srcPoints[i] = queryifeyPoint[matches[i].queryIdx].pt;
dstPoints[i] = trainieyPoint[matches[i].trainIdx].pt;
}
//匹配點(diǎn)對(duì)進(jìn)行RANSAC過(guò)濾
vector<int> inliersMask(srcPoints.size());
// Mat homography;
//homography = findHomography(srcPoints, dstPoints, RANSAC, 5, inliersMask);
findHomography(srcPoints, dstPoints, RANSAC, 5, inliersMask);
//手動(dòng)的保留RANSAC過(guò)濾后的匹配點(diǎn)對(duì)
for (int i = 0; i < inliersMask.size(); i++)
{
if (inliersMask[i])
{
kmatches_ransac.push_back(matches[i]);
}
}
}
int test5()
{
Mat img1, img2;
img1 = imread("F:/testMap/box.png");
img2 = imread("F:/testMap/box_in_scen.png");
if (!(img1.data && img2.dataend))
{
cout << "讀取圖像錯(cuò)誤,請(qǐng)確認(rèn)圖像文件是否正確" << endl;
return -1;
}
//提取ORB特征點(diǎn)
vector<KeyPoint> Keypoints1, Keypoints2;
Mat descriptions1, descriptions2;
//計(jì)算特征點(diǎn)
orb_features(img1, Keypoints1, descriptions1);
orb_features(img2, Keypoints2, descriptions2);
//特征點(diǎn)匹配
vector<DMatch> matches, good_min, good_ransac;
BFMatcher matcher(NORM_HAMMING);
matcher.match(descriptions1, descriptions2, matches);
cout << "matches=" << matches.size() << endl;
//最小漢明距離
match_min(matches, good_min);
cout << "good_min=" << good_min.size() << endl;
//用ransac算法篩選匹配結(jié)果
ransac(good_min, Keypoints1, Keypoints2, good_ransac);
cout << "good_matches.size=" << good_ransac.size() << endl;
//繪制匹配結(jié)果
Mat outimg, outimg1, outimg2;
drawMatches(img1,Keypoints1,img2,Keypoints2, matches,outimg);
drawMatches(img1, Keypoints1, img2, Keypoints2, good_min, outimg1);
drawMatches(img1,Keypoints1,img2,Keypoints2, good_ransac,outimg2);
imshow("未篩選結(jié)果", outimg);
imshow("最小漢明距離篩選", outimg1) ;
imshow("ransac篩選",outimg2);
waitKey(0);
return 0;
}
6、相機(jī)模型與投影
?
?
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-569143.html
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-569143.html
//相機(jī)模型與投影
int test4()
{
//輸入計(jì)算得到的內(nèi)參矩陣和畸變矩陣
Mat cameraMatrix = (Mat_<float>(3,3) << 532.016297,0,332.172519,0,531.565159,233.388075,0, 0,1);
Mat distCoeffs = (Mat_<float>(1,5) << -0.285188,0.080097,0.001274,-0.002415,0.106579);
//代碼清單10-10中計(jì)算的第一張圖像相機(jī)坐標(biāo)系與世界坐標(biāo)系之間的關(guān)系
Mat rvec = (Mat_<float>(1,3)<<-1.977853,-2.002220,0.130029);
Mat tvec = (Mat_<float>(1,3) <<-26.88155,-42.79936,159.19703);
//生成第一張圖像中內(nèi)角點(diǎn)的三維世界坐標(biāo)
Size boardSize = Size(9, 6);
Size squareSize = Size(10,10);//棋盤(pán)格每個(gè)方格的真實(shí)尺寸
vector<Point3f> PointSets;
for (int j = 0; j < boardSize.height; j++)
{
for (int k = 0; k < boardSize.width; k++)
{
Point3f realPoint;
//假設(shè)標(biāo)定板為世界坐標(biāo)系的z平面,即z=0
realPoint.x = j*squareSize.width;
realPoint.y = k*squareSize.height;
realPoint.z = 0;
PointSets.push_back(realPoint);
}
}
//根據(jù)三維坐標(biāo)和相機(jī)與世界坐標(biāo)系時(shí)間的關(guān)系估計(jì)內(nèi)角點(diǎn)像素坐標(biāo)
vector<Point2f>imagePoints;
projectPoints(PointSets,rvec,tvec,cameraMatrix, distCoeffs, imagePoints);
for(int i = 0; i < imagePoints.size(); i++)
{
cout << "第" << to_string(i) << "個(gè)點(diǎn)的坐標(biāo)" << imagePoints[i] << endl;
}
waitKey(0);
return 0;
}
到了這里,關(guān)于Shi-Tomas角點(diǎn)檢測(cè)、亞像素級(jí)別角點(diǎn)位置優(yōu)化、ORB特征點(diǎn)、特征點(diǎn)匹配、RANSAC優(yōu)化特征點(diǎn)匹配、相機(jī)模型與投影的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!