英文:
Find closest point on HoughLine
问题
给定一个霍夫线 {rho: number, theta: number}
和一个坐标点 {x: number, y: number}
,我该如何找到该霍夫线上距离给定坐标点最近的点?
所以在下面的示例图中,我有蓝线和红点,我正在寻找白色十字交点。
我正在使用 TypeScript,但我希望得到任何语言或格式的答案,因为这实际上更多是一个数学问题。
英文:
Given a hough line as {rho: number, theta: number}
and a coordinate as {x: number, y: number}
, how would I find the closest point on that hough line to the given coordinate?
So in the following sample graphic, I have the blue line and the red dot, and I'm looking for the white cross.
I'm using Typescript, but I'd appreciate answers in any language or format, since this is technically more of a math problem.
答案1
得分: 2
白色交叉点是红色点“C”投影到线上的位置。
首先获取垂直于线的法向量分量:
nx = cos(theta)
ny = sin(theta)
线的方向向量是:
dx = -ny
dy = nx
要找到这个投影,我们需要线上的一些点“A”。假设这个点是:
ax = rho * nx
ay = rho * ny
然后得到向量AC:
acx = cx - ax
acy = cy - ay
现在使用点积计算投影:
coeff = dx * acx + dy * acy
px = ax + dx * coeff
py = ay + dy * coeff
快速编写的Python测试(未经充分测试):
import math
def projection_onto_houghline(rho, theta, cx, cy):
dx = -math.sin(theta)
dy = math.cos(theta)
ax = rho * dy
ay = -rho * dx
acx = cx - ax
acy = cy - ay
coeff = dx * acx + dy * acy
px = ax + dx * coeff
py = ay + dy * coeff
return(px, py)
print(projection_onto_houghline(math.sqrt(2), math.pi/4, 0, 0))
print(projection_onto_houghline(math.sqrt(2), math.pi/4, 2.5, 2))
输出结果为:
(1.0000000000000002, 1.0000000000000002)
(1.2500000000000002, 0.7500000000000002)
英文:
White cross is projection of red point C
onto the line.
At first get components of normal vector to line
nx = cos(theta)
ny = sin(theta)
and direction vector of line is
dx = -ny
dy = nx
To find this projection, we need some point A
at the line. Let's this point is
ax = rho * nx
ay = rho * ny
and get vector AC
acx = cx - ax
acy = cy - ay
Now calculate projection using dot product
coeff = dx*acx + dy*acy
px = ax + dx * coeff
py = ay + dy * coeff
Quick-made Python test (not well tested)
import math
def projection_onto_houghline(rho, theta, cx, cy):
dx = -math.sin(theta)
dy = math.cos(theta)
ax = rho * dy
ay = -rho * dx
acx = cx - ax
acy = cy - ay
coeff = dx*acx + dy*acy
px = ax + dx * coeff
py = ay + dy * coeff
return(px, py)
print(projection_onto_houghline(math.sqrt(2), math.pi/4, 0, 0))
print(projection_onto_houghline(math.sqrt(2), math.pi/4, 2.5, 2))
(1.0000000000000002, 1.0000000000000002)
(1.2500000000000002, 0.7500000000000002)
答案2
得分: 0
对于红点 C
,你应该做的是:
- 计算点
C
的切线方向分量。 - 在步骤1的基础上添加
rho * N
(其中,N是线的单位法向量)。
备忘录(上述内容的含义)
例如,如果问题是“线是 x=x0”,该怎么办?
在这种情况下,只需修改点 C
的x分量值为 x0
。
上述步骤实际上是在另一个坐标系统上执行此操作。坐标系的基础是线的法向量和切向量。
//此代码示例是C++代码,使用OpenCV进行可视化
//
#include <random>
class Rnd
{
public:
Rnd() : m_MT( std::random_device().operator()() ){}
double GetReal( double Min, double Max ){ return std::uniform_real_distribution<double>( Min,Max )( m_MT ); }
private:
std::mt19937 m_MT;
};
//主函数
int main()
{
constexpr int ImgSize = 320;
cv::Mat ShowImg = cv::Mat::zeros( ImgSize,ImgSize, CV_8UC3 );
constexpr int nTest = 3;
const cv::Scalar DrawColor[nTest] = { {255,96,96}, {0,255,0}, {0,0,255} };
Rnd rnd;
for( int i=0; i<nTest; ++i )
{
//线参数
double rho = rnd.GetReal( 10, ImgSize-10 );
double theta = rnd.GetReal( 0, CV_PI*0.5 );
cv::Vec2d N{ cos(theta), sin(theta) }; //线的单位法向量
cv::Vec2d T{ -N[1], N[0] }; //线的单位切向量
//点C
cv::Vec2d C{ rnd.GetReal( 0, ImgSize ), rnd.GetReal( 0, ImgSize ) };
//答案点X
//你应该计算的就是这个。
cv::Vec2d X = T*C.dot(T) + rho*N;
{//绘制结果
{//绘制线
cv::Vec2d A = rho * N;
cv::Vec2d P1 = A - ImgSize * T;
cv::Vec2d P2 = A + ImgSize * T;
cv::line( ShowImg, cv::Point(P1), cv::Point(P2), DrawColor[i], 2 );
}
{//绘制点C和X
cv::circle( ShowImg, cv::Point(C), 5, DrawColor[i], -1 );
cv::circle( ShowImg, cv::Point(X), 5, DrawColor[i], -1 );
cv::line( ShowImg, cv::Point(C), cv::Point(X), DrawColor[i]*0.6 );
}
}
}
cv::imshow( "Result", ShowImg );
cv::waitKey();
return 0;
}
这是上述代码的结果。
- 以不同颜色绘制了3个示例。
- 线条绘制得稍厚。
英文:
For the red point C
, what you should do is
- Calculate line tangential directional component of the
C
- Add
rho * N
to 1. (where, N is unit normal vector of the line)
memo (: meaning of above)
For example, if problem is "line is x=x0", what to do?
This case, just modify the x component value of the point C
to x0
.
Above steps is just doing this but on another coordinate system. Basis of the coordinate system is normal and tangential of the line.
//This code sample is C++, and using OpenCV to visualize
//
#include <random>
class Rnd
{
public:
Rnd() : m_MT( std::random_device().operator()() ){}
double GetReal( double Min, double Max ){ return std::uniform_real_distribution<double>( Min,Max )( m_MT ); }
private:
std::mt19937 m_MT;
};
//main
int main()
{
constexpr int ImgSize = 320;
cv::Mat ShowImg = cv::Mat::zeros( ImgSize,ImgSize, CV_8UC3 );
constexpr int nTest = 3;
const cv::Scalar DrawColor[nTest] = { {255,96,96}, {0,255,0}, {0,0,255} };
Rnd rnd;
for( int i=0; i<nTest; ++i )
{
//Line Parameter
double rho = rnd.GetReal( 10, ImgSize-10 );
double theta = rnd.GetReal( 0, CV_PI*0.5 );
cv::Vec2d N{ cos(theta), sin(theta) }; //Line Unit Normal
cv::Vec2d T{ -N[1], N[0] }; //Line Unit Tangential
//The Point C
cv::Vec2d C{ rnd.GetReal( 0, ImgSize ), rnd.GetReal( 0, ImgSize ) };
//The Answer Point X
//What you should calculate is this.
cv::Vec2d X = T*C.dot(T) + rho*N;
{//Draw Result
{//Draw Line
cv::Vec2d A = rho * N;
cv::Vec2d P1 = A - ImgSize * T;
cv::Vec2d P2 = A + ImgSize * T;
cv::line( ShowImg, cv::Point(P1), cv::Point(P2), DrawColor[i], 2 );
}
{//Draw Point C and X
cv::circle( ShowImg, cv::Point(C), 5, DrawColor[i], -1 );
cv::circle( ShowImg, cv::Point(X), 5, DrawColor[i], -1 );
cv::line( ShowImg, cv::Point(C), cv::Point(X), DrawColor[i]*0.6 );
}
}
}
cv::imshow( "Result", ShowImg );
cv::waitKey();
return 0;
}
This is a result of above code.
- 3 examples are drawn in different colors.
- Lines are drawn slightly thicker
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论