1、绘制直线
绘制直线函数是cv::line,函数完整形式如下
void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);
/*
@param img 图像
@param pt1 线段端点1
@param pt2 线段端点2
@param color 线段颜色
@param thickness 线宽
@param lineType 线的类型
@param shift 点坐标的小数位偏移
*/
color可以使用cv::Scalar构造,但是传入参数的顺序是BGR,使用CV_RGB宏更直观,以RGB顺序传入;
lineType取值有LINE_4、LINE_8和LINE_AA,分别表示4连接线,8连接线,抗锯齿线,是以不同的算法产生直线(也可以是FILLED=-1,直接填充);
shift是指点坐标的二进制表示的位偏移,每加1坐标值减一半,实验的结果,不知道理解的对不对,使用默认值0就可以了;
在两个点之间绘制线宽为1的红色直线定义为一个函数
void DrawLine(const cv::Mat& destImg, const cv::Point& pt1, const cv::Point& pt2)
{
cv::line(destImg, pt1, pt2, CV_RGB(255, 0, 0), 1);
}
下面的实例在鼠标两次点击位置中间画一根直线,绘制完成可以按Enter键保存图像。
cv::Mat g_originImage;//原始图像
cv::Mat g_editImage;//编辑的图像
std::vector<cv::Point> g_editPoints;//正在绘制的图形的点
std::vector<std::vector<cv::Point>> g_lines;//所有的线段
void RedrawAllLines()
{
g_originImage.copyTo(g_editImage);//恢复背景图像
for (int i = 0; i < g_lines.size(); i++)
{
if (g_lines[i].size() >= 2)
{
DrawLine(g_editImage,g_lines[i][0], g_lines[i][1]);
}
}
}
void OnDrawLineMouseEvent(int event, int x, int y, int flags, void* userdata)
{
if (event == cv::EVENT_LBUTTONDOWN)
{
if (g_editPoints.size() > 0)
{
//在第二个点按下鼠标之后添加到线段列表中,并重绘图像
g_editPoints.push_back(cv::Point(x, y));
g_lines.push_back(g_editPoints);
RedrawAllLines();
g_editPoints.clear();
imshow("image", g_editImage);
}
else
{
g_editPoints.push_back(cv::Point(x, y));//第一个点
}
}
else if (event == cv::EVENT_MOUSEMOVE)
{
if (g_editPoints.size() > 0)
{
//鼠标移动中,绘制到鼠标位置的直线,但鼠标当前点不加入到g_editPoints中
RedrawAllLines();
DrawLine(g_editImage,g_editPoints[g_editPoints.size() - 1], cv::Point(x, y));
imshow("image", g_editImage);
}
}
}
int main(int argc, char **arv)
{
g_originImage = cv::imread("walkers.jpg");
g_originImage.copyTo(g_editImage);