图像中求点到直线的垂足

已知图像中线段的两个点,求另外一个点到这个点的垂足。

一、垂足公式

  • 已知直线一般式方程时:
    设已知直线外一点坐标为 ( 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(yy0)/(xx0)=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 ) x=(BBx0ABy0AC)/(AA+BB)y=(ABx0+AAy0BC)/(AA+BB)

  • 直线的斜截式方程:

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 ABC

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=k;B=1.0;C=pntSart.ykpntSart.x

再将以上 A 、 B 、 C A、B、C ABC分别代入垂足公式即可

二、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;
}

显示如下:
在这里插入图片描述

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值