影象中求點到直線的垂足
技術標籤:個人筆記|數字影象處理(c++)
已知影象中線段的兩個點,求另外一個點到這個點的垂足。
一、垂足公式
-
已知直線一般式方程時:
設已知直線外一點座標為 ( x 0 , y 0 ) (x0,y0) (x0,y0),垂足座標為 ( x , y ) (x,y) (x,y),因為垂線與直線垂直,垂線斜率為 k k k的負倒數,則可得方程:
A x + B y + C = 0 ( y − y 0 ) / ( x − x 0 ) = B / A ; Ax + By + C = 0\\ (y - y0) / (x - x0) = B / A; Ax+By+C=0(y−y0)/(x−x0)=B/A;
解方程可得垂足座標為
x = ( B ∗ B ∗ x 0 − A ∗ B ∗ y 0 − A ∗ C ) / ( A ∗ A + B ∗ B ) y = ( − A ∗ B ∗ x 0 + A ∗ A ∗ y 0 − B ∗ C ) / ( A ∗ A + B ∗ B ) x = ( B*B*x0 - A*B*y0 - A*C ) / ( A*A + B*B )\\ y = ( -A*B*x0 + A*A*y0 - B*C ) / ( A*A + B*B ) -
直線的斜截式方程:
y = k x + b = − ( A / B ) y − ( C / B ) y = kx + b =- (A/B)y - (C/B) y=kx+b=−(A/B)y−(C/B)
計算得出 A 、 B 、 C A、B、C A、B、C
A
=
k
;
B
=
−
1.0
;
C
=
p
n
t
S
a
r
t
.
y
−
k
∗
p
n
t
S
a
r
t
.
x
A = k;\\ B = -1.0;\\ C = pntSart.y - k * pntSart.x
A=
再將以上
A
、
B
、
C
A、B、C
A、B、C分別代入垂足公式即可
二、C++程式碼
呼叫Opencv庫來做Demo
寫程式碼時,別忘記了考慮斜率無窮大的問題
#include <iostream>
#include "opencv2/opencv.hpp"
void FindFoot(cv::Point2f pntSart, cv::Point2f pntEnd, cv::Point2f pA, cv::Point2f &pFoot)
{
float k = 0.0;
if (pntSart.x == pntEnd.x)
{
pFoot.x = pntSart.x;
pFoot.y = pA.y;
return;
}
k = (pntEnd.y - pntSart.y) * 1.0 / (pntEnd.x - pntSart.x);
float A = k;
float B = -1.0;
float C = pntSart.y - k * pntSart.x;
pFoot.x = (B * B * pA.x -A * B * pA.y-A * C) / (A * A + B * B);
pFoot.y = (A * A * pA.y - A * B * pA.x-B * C) / (A * A + B * B);
}
int main()
{
cv::Mat matBgrImg = cv::Mat(300, 300, CV_8UC3, cv::Scalar(0,0,0));
std::cout << matBgrImg.cols << std::endl;
cv::Point2f p1(100, 100);
cv::Point2f p2(200, 200);
cv::Point2f pA(100, 200);
cv::Point2f pFoot;
FindFoot(p1, p2, pA, pFoot);
std::cout << pFoot.x << " " << pFoot.y << std::endl;
cv::line(matBgrImg, p1, p2, cv::Scalar(0, 255, 255, 0), 2);
cv::line(matBgrImg, pA, pFoot, cv::Scalar(255, 0, 0, 0), 2);
cv::imshow("name", matBgrImg);
cv::waitKey(0);
std::cout << "Hello, World!" << std::endl;
return 0;
}
顯示如下: