用到的头文件
#include<iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
先构建一个齐次坐标的类,在私有成员变量中加入两个bool类型的isPoint与isLine零个成员变量以判断这个齐次坐标是点还是线(这个有点麻烦,后续可能优化);
在类中包含了对齐次坐标的检查check函数,防止输入时两个bool值都为1或0;
包含了regulation函数,方便对点或线(不必要)的归一化方法,这样有助于 后续算法的计算,以及对点显示;
包含了draw函数,可以在给定的任意画布中显示齐次坐标所显示的点或线,并对异常特殊显示;
class Coordinates2d
{
public:
Coordinates2d() :x(0), y(0), isPoint(0), isLine(0) { cout << "无参构造函数" << endl; }
Coordinates2d(int x, int y, bool a, bool b) :x(x), y(y), isPoint(a), isLine(b) { cout << "有参构造函数" << endl; }
Coordinates2d(int x, int y, int z, bool a, bool b) :x(x), y(y), z(z), isPoint(a), isLine(b) { cout << "有参构造函数" << endl; }
Coordinates2d(const Coordinates2d& p) {
x = p.x;
y = p.y;
z = p.z;
isPoint = p.isPoint;
isLine = p.isLine;
cout << "复制构造函数" << endl;
}
~Coordinates2d() { cout << "析构函数" << endl; }
inline float getX() { return x; }
inline float getY() { return y; }
inline float getZ() { return z; }
//统一输出,方便后续检查
inline void print() {
cout << "x=" << x << endl;
cout << "y=" << y << endl;
cout << "z=" << z << endl;
cout << "这是:" << PointOrLine() << endl;
}
//点return 0,线return 1,异常return -1;
inline int check() {
if ((isPoint ^ isLine) == 0) { return -1; }
else if (isLine == 1) { return 1; }
else { return 0; }
};
//以中文返回,好看一点
inline string PointOrLine() {
if (check() == -1) { return "啥也不是"; }
else if (check() == 0) { return "点"; }
else { return "线"; }
}
//将齐次坐标归一化
void regulation() {
if (check() != -1 && z != 1 && z != 0) {
x = x / z;
y = y / z;
z = 1.0;
}
else if (check() == -1) { cout << "点线不明确" << endl; }
else { cout << "不能regulation" << endl; }
};
//画绿色的点与红色的线;
void draw(Mat& background) {
if (check() == -1) {
cv::Point pt(background.cols/10, background.rows/2);
cv::putText(background, "Warning!!!", pt, 1, 5, cv::Scalar(128, 128, 128),2,8);
}
else if (check() == 0) {
cv::Point pt(x/z, y/z);
cv::circle(background, pt, 3, cv::Scalar(0, 255, 0), -1);
}
else {
cv::Point pt1( -z/x,0);
cv::Point pt2((-z-background.rows*y)/x, background.rows);
cout << pt1 << endl;
cout << pt2 << endl;
cv::line(background, pt1,pt2, cv::Scalar(0, 0, 255), 1);
}
}
private:
float x;
float y;
float z = 1.0;
bool isPoint;
bool isLine;
};
求解两直线的交点的齐次坐标函数
//检查输入两线,返回点
Coordinates2d jiaodian(Coordinates2d& co1, Coordinates2d& co2)
{
if (0 == co1.getX() * co2.getY() - co1.getY() * co2.getX()) { cout << "两条平行线没有交点!!!!" << endl; }
else if (co1.check() == 1 && co2.check() == 1) {
float x = co1.getY() * co2.getZ() - co1.getZ() * co2.getY();
float y = -co1.getX() * co2.getZ() + co1.getZ() * co2.getX();
float z = co1.getX() * co2.getY() - co1.getY() * co2.getX();
Coordinates2d res(x, y, z, 1, 0);
res.regulation();
return res;
}
else {
cout << "输入有误!!!!!!!!" << endl;
}
}
求解两点所确定的直线的齐次坐标函数
//检查输入两点,返回线
Coordinates2d jiaoxian(Coordinates2d& co1, Coordinates2d& co2)
{
if ((co1.getX() / co2.getX() == co1.getY() / co2.getY()) && (co1.getX() / co2.getX() == co1.getZ() / co2.getZ())) { cout << "同一个点无法确定唯一直线!!!!" << endl; }
else if (co1.check() == 0 && co2.check() == 0) {
float x = co1.getY() * co2.getZ() - co1.getZ() * co2.getY();
float y = -co1.getX() * co2.getZ() + co1.getZ() * co2.getX();
float z = co1.getX() * co2.getY() - co1.getY() * co2.getX();
Coordinates2d res(x, y, z, 0, 1);
return res;
}
else {
cout << "输入有误!!!!!!!!" << endl;
}
}
主函数部分1:给定两条直线,求解交点,并做图
int main() {
Coordinates2d co1(300, -100, 3, 0, 1);
Coordinates2d co2(200, -80, 400, 0, 1);
Coordinates2d co3 = jiaodian(co1, co2);
co3.print();//输出信息
cv::Mat a(480, 640, CV_8UC3, cv::Scalar(0, 0, 0));//创造一个 480×640的黑布
co1.draw(a);
co2.draw(a);
co3.draw(a);
cv::imshow("reslt",a);
cv:waitKey(0);
}
主函数部分2:给定两个点,求解确定的直线,并做图
int main() {
Coordinates2d co1(300, 100, 1, 1, 0);
Coordinates2d co2(200, 80, 4, 1, 0);
Coordinates2d co3 = jiaoxian(co1, co2);
co3.print();//输出信息
cv::Mat a(480, 640, CV_8UC3, cv::Scalar(0, 0, 0));//创造一个 480×640的黑布
co1.draw(a);
co2.draw(a);
co3.draw(a);
cv::imshow("reslt",a);
cv:waitKey(0);
}
主函数部分3:给定异常的值时(比如两线求交线,两点求交点时,或者直接无法判断时点 还是线时),生成warning图