opencv系列之一 利用透視變換實現影象的俯檢視(正檢視)
課題需要,前段時間一直在研究鳥瞰圖,因為當攝像機和目標物有一個傾斜角的時候,採集到的影象會有一個透視畸變,而我們做影象處理,需要得到的是感興趣部分的正檢視,如下面兩幅圖所示。而我發現,鳥瞰圖實現不了我想要的功能,因為我只需要感興趣部分就可以了。後來發現,採用透視變換和透視矯正,可以很好的實現這個功能。下面詳細地介紹了這個方法。
具體流程為:
a)載入影象→灰度化→邊緣處理得到邊緣影象(edge map)
cv::Mat im = cv::imread(filename);
cv::Mat gray;
cvtColor(im,gray,CV_BGR2GRAY);
Canny(gray,gray,100,150,3);
b)霍夫變換進行直線檢測,此處使用的是probabilistic Hough transform(cv::HoughLinesP)而不是standard Hough transform(cv::HoughLines)
std::vector<Vec4i> lines;
cv::HoughLinesP(gray,lines,1,CV_PI/180,70,30,10);
for(int i = 0; i < lines.size(); i++)
line(im,cv::Point(lines[i][0],lines[i][1]),cv::Point(lines[i][2],lines[i][3]),Scalar(255,0,0),2,8,0);
c)通過上面的圖我們可以看出,通過霍夫變換檢測到的直線並沒有將整個邊緣包含,但是我們要求的是四個頂點所以並不一定要直線真正的相交,下面就要求四個頂點的座標,公式為:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
cv::Point2f
computeIntersect(cv::Vec4i a, cv::Vec4i b)
{
int x1
= a[0], y1 = a[1], x2 = a[2], y2 = a[3];
int x3
= b[0], y3 = b[1], x4 = b[2], y4 = b[3];
if ( float d
= (( float )(x1-x2)
* (y3-y4)) - ((y1-y2) * (x3-x4)))
{
cv::Point2f
pt;
pt.x
= ((x1*y2 - y1*x2) * (x3-x4) - (x1-x2) * (x3*y4 - y3*x4)) / d;
pt.y
= ((x1*y2 - y1*x2) * (y3-y4) - (y1-y2) * (x3*y4 - y3*x4)) / d;
return pt;
}
else
return cv::Point2f(-1,
-1);
}
|
1 2 3 4 5 6 7 8 9 10 |
std::vector<cv::Point2f>
corners;
for ( int i
= 0; i < lines.size(); i++)
{
for ( int j
= i+1; j < lines.size(); j++)
{
cv::Point2f
pt = computeIntersect(lines[i], lines[j]);
if (pt.x
>= 0 && pt.y >= 0)
corners.push_back(pt);
}
}
|