由于视频是一帧帧刷新的,常见的绘图方法只适用于不变的Mat上,而视频播放下一帧之后上一帧所绘制的图像则随着上一帧被刷掉了,而MFC则是创建一块DC,在DC内画所以原理不同。为了实现在视频和摄像头画面中进行绘图,则需要将绘图点保存在容器中,并在每帧播放的时候都要进行绘图,才能实现连贯的绘图。而OPENCV利用Circle进行画曲线画出来的线是离散的很容易断,与MFC效果又差太远,故想出了利用Polylines和Circle同时绘画,重合出一条连贯的实线,但因此这种方法性能很差,不知有没有其他实现曲线的办法,如果有可以评论区教教我嘻嘻
#include#include #include #include using namespace std; using namespace cv; bool g_bDrawing = false; Point g_nCurrPoint; Point g_nEndPoint; vector > vecDrawPoint; pair tempPoint; vector vecCircle; vector vecpoly; vector > vecCirLine; void onMouse(int event, int x, int y, int flag, void* param) { Mat& img = *(cv::Mat*)param; switch (event) { //移动鼠标的时候 case CV_EVENT_MOUSEMOVE: { if (g_bDrawing == true) { g_nEndPoint = Point(x, y); tempPoint.first = g_nCurrPoint; tempPoint.second = g_nEndPoint; vecCircle.push_back(g_nEndPoint); vecpoly.push_back(g_nEndPoint); } } break; //点击鼠标左键时 case CV_EVENT_LBUTTONDOWN: { g_bDrawing = true; g_nCurrPoint = Point(x, y); } break; //松开鼠标左键时 case CV_EVENT_LBUTTONUP: { g_bDrawing = false; g_nEndPoint = Point(x, y); if (g_nEndPoint != g_nCurrPoint) { pair linePoint(g_nCurrPoint, g_nEndPoint); vecDrawPoint.push_back(linePoint); } vecpoly.clear(); } break; } } void DrawRectangle(Mat matFrame) { rectangle(matFrame, tempPoint.first, tempPoint.second, Scalar(255, 255, 0), 2); if (!vecDrawPoint.empty()) { for (int i = 0; i < vecDrawPoint.size(); i++) { rectangle(matFrame, vecDrawPoint[i].first, vecDrawPoint[i].second, Scalar(255, 255, 0), 2); } } } void DrawLine(Mat matFrame) { line(matFrame, tempPoint.first, tempPoint.second, Scalar(255, 255, 0), 1, CV_AA); if (!vecDrawPoint.empty()) { for (int i = 0; i < vecDrawPoint.size(); i++) { line(matFrame, vecDrawPoint[i].first, vecDrawPoint[i].second, Scalar(255, 255, 0), 1, CV_AA); } } } void DrawCir(Mat matFrame) { for (int i = 0; i < vecCircle.size(); i++) { circle(matFrame, vecCircle[i], 0, Scalar(255, 255, 0), 2, CV_AA); } if (!vecCircle.empty()) { vecCirLine.push_back(vecpoly); for (int i = 0; i < vecCirLine.size(); i++) { polylines(matFrame, vecCirLine[i], false, Scalar(255, 255, 0), 2); } } } int main() { int nDrawType = 2;//设置绘图类型 1:直线 2:矩形 3:曲线 string strPath= "E:/test.avi"; VideoCapture Vcap; VideoWriter writer(strPath, 1, Vcap.get(CAP_PROP_FPS), cv::Size(Vcap.get(CAP_PROP_FRAME_WIDTH), Vcap.get(CAP_PROP_FRAME_HEIGHT)),true); Vcap.open(0);//为0时获取第一个摄像头设备画面,为路径时则打开路径指向的视频文件 if (!Vcap.isOpened()) { return 0; } Mat matFrame; namedWindow("video", 0); setMouseCallback("video", onMouse, (void*)&matFrame); while (1) { Vcap >> matFrame; //Canny(matFrame, matCFrame, 20, 100,3);//边缘检测 if (matFrame.empty()) { break; } switch (nDrawType) { case 1: DrawLine(matFrame);//画直线 break; case 2: DrawRectangle(matFrame);//画矩形 break; case 3: DrawCir(matFrame);//画曲线 break; default: break; } writer.write(matFrame); imshow("video", matFrame); if (waitKey(60) > 0) { break; } } Vcap.release(); destroyAllWindows(); return 0; }



