首先通過鼠標操作在圖片上隨機點兩個點,創建一條直線。然後點第三個點,該點到直線的距離就出來了。
由於鼠標點擊有誤差,所以測的距離有誤差,還請大佬指點!
#include "opencv2/opencv.hpp"
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
//定義一個計算兩點距離的函數
double getDistance(CvPoint pointO, CvPoint pointA)
{
double distance;
distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);
distance = sqrtf(distance);
return distance;
}
//定義一個將長整形轉換成字符串型的函數
string convertToString(long d)
{
ostringstream os;
if (os << d)
return os.str();
return "invalid conversion";
}
//定義全局變量
static Mat img_src;
static Point point1 = Point(0, 0);//第一個點(x1,y1)
static Point point2 = Point(0, 0);//第二個點(x2,y2)
static Point point3 = Point(0, 0);//第三個點(x3,y3)
static Point point4;//第四個點(x4,y4)
static Point point5;
static Point mouse_dot;
static string window_name = "image";
//定義鼠標事件函數
static void onMouse(int event, int x, int y, int, void*)
{
if (CV_EVENT_LBUTTONDOWN == event)//鼠標左鍵按下
{
mouse_dot = Point(x, y);//接收按下點的座標並賦值
if (point1.x == 0 && point1.y == 0)//接收第一個點
{
point1 = mouse_dot;
point5 = mouse_dot;
}
else if (point2.x == 0 && point2.y == 0)//接收第二個點
{
point2 = mouse_dot;
point5 = mouse_dot;
}
else if (point3.x == 0 && point3.y == 0)//接收第三個點
{
point3 = mouse_dot;
point5 = mouse_dot;
}
}
else if (CV_EVENT_LBUTTONUP == event)//鼠標左鍵鬆開
{
circle(img_src, point5, 2, Scalar(255, 0, 0), 2);//用小圓標誌按下的點
imshow("output", img_src);//並將小圓點顯示在圖片上
//如果在圖片上點擊完3個點後,將進行下面的操作
if (point3.x != 0 && point3.y != 0)
{
//計算點point3到直線的距離,並求出直線上的點point4,連接point3和point4,並輸出兩點距離
//建立直線方程Ax+By+C=0-->(y2-y1)*x+(x1-x2)*y+(x2*y1-x1*y2)=0
long A = point2.y - point1.y;
long B = point1.x - point2.x;
long C = point2.x*point1.y - point1.x*point2.y;
long a = A*A;
long b = B*B;
//直線距離公式D=|A*x3+B*y3+C|/sqrt(A^2+B^2)
long w = (A*point3.x + B*point3.y + C);
if (w < 0) w = 0 - w;//取絕對值
long D = long(w / sqrt(a + b));
//利用公式x4=(x3*B^2-AB*y3-AC)/(A^2+B^2)和A*x4+B*y4+C=0求出直線上的點
point4.x = int((b*point3.x - A*B*point3.y - A*C) / (a + b));
if (B == 0) point4.y = point3.y;//排除分母爲零的情況
else point4.y = int((-C - A*point4.x) / B);
circle(img_src, point4, 2, Scalar(255, 0, 0), 2);
line(img_src, point3, point4, Scalar(255, 255, 255), 1, 8);
//確定文字在圖片上顯示的位置,並輸出文字
int wedth = (point3.x + point4.x) / 2 ;
int height = (point3.y + point4.y) / 2-10;
string length = convertToString(D);
putText(img_src, length, Point(wedth, height), CV_FONT_HERSHEY_SIMPLEX, 0.4, Scalar(255, 255, 255), 1, 8);
//把所有的點歸零,才能進行下次操作
point1 = Point(0, 0);
point2 = Point(0, 0);
point3 = Point(0, 0);
point4 = Point(0, 0);
imshow("output", img_src);//刷新圖片
waitKey(0);
}
//點擊了兩個點後,用直線連接兩個點
else if (point2.x != 0 && point2.y != 0)
{
line(img_src, point1, point2, Scalar(255, 255, 255), 1, 8);
imshow("output", img_src);//刷新圖片
}
}
}
int main(int argc, char** argv)
{
img_src = imread("zheng_lingjian2.png");
if (!img_src.data)
{
cout << "the image isn't loaded..." << endl;
return -1;
}
namedWindow(window_name, CV_WINDOW_AUTOSIZE);
setMouseCallback(window_name, onMouse, 0);//執行鼠標操作,且只能在image窗口進行鼠標點擊
while (true)
{
imshow(window_name, img_src);
int c = waitKey(0);
//通過Esc鍵退出程序
if ((c & 255) == 27)
{
destroyAllWindows();
cout << "Exiting ...\n";
break;
}
}
return 0;
}