需求描述
在图像显示界面中,鼠标左键按下并拖动,实时框选ROI,松开后得到ROI矩形框。可多次重新框选,以回车键结束框选。得到最终的ROI信息。
C++代码实现
#include"opencv2/opencv.hpp"
#include"opencv2/highgui.hpp"
// 鼠标事件数据结构体
struct onMouseData
{
public:
cv::Mat kSrcImg; // 原始图像
cv::Mat kDrawImg; // 绘图图像
cv::Point kPointer; // 当前鼠标坐标
cv::Point kRectTopLeft; // ROI左上角坐标
cv::Point kRectBottomRight; // ROI左下角坐标
cv::Rect kRoi; // ROI矩形框信息
cv::Scalar kLineColor; // 矩形框线条颜色
int kLineWidth; // 矩形框线条款图
std::string kWiddget; // 绘图窗口名
bool isDrawing; // 当前是否正在绘制ROI
onMouseData()
{
kLineColor = cv::Scalar(0, 0, 255);
kRectTopLeft = {-1, -1};
kRectBottomRight = {-1, -1};
kPointer = {-1, -1};
isDrawing = false;
kLineWidth = 1;
}
};
// 实时绘制ROI
void drawRoi(onMouseData* kMouseData);
// 鼠标事件回调函数
void onMouseCallBack(int event, int x, int y, int flags, void* param);
// ROI选择功能函数
void selectROI(const std::string& kWiddget, const cv::Mat& kSrcImg, onMouseData& kMouseData);
int main() {
cv::Mat kSrcImg = cv::imread("..\\..\\data\\4.1.01.tiff");
std::string mainWidget = "ROI框选";
cv::namedWindow(mainWidget, cv::WINDOW_KEEPRATIO);
cv::resizeWindow(mainWidget, 256, 256);
onMouseData kMouseData;
selectROI(mainWidget, kSrcImg, kMouseData);
std::cout << kMouseData.kRoi << std::endl;
system("pause");
cv::destroyAllWindows();
return 0;
}
void drawRoi(onMouseData* kMouseData)
{
if(kMouseData->isDrawing)
{
kMouseData->kRoi.x = kMouseData->kRectTopLeft.x;
kMouseData->kRoi.y = kMouseData->kRectTopLeft.y;
kMouseData->kRoi.width = kMouseData->kPointer.x - kMouseData->kRectTopLeft.x;
kMouseData->kRoi.height = kMouseData->kPointer.y - kMouseData->kRectTopLeft.y;
cv::rectangle(kMouseData->kDrawImg,
kMouseData->kRoi,
kMouseData->kLineColor,
kMouseData->kLineWidth, cv::LINE_8, 0);
cv::imshow(kMouseData->kWiddget, kMouseData->kDrawImg);
}
}
void onMouseCallBack(int event, int x, int y, int flags, void* param)
{
onMouseData* kMouseData = reinterpret_cast<onMouseData*>(param);
kMouseData->kDrawImg = kMouseData->kSrcImg.clone();
kMouseData->kPointer = {x, y};
switch(event)
{
case cv::EVENT_LBUTTONDOWN:
kMouseData->kRectTopLeft = kMouseData->kPointer;
kMouseData->isDrawing = !kMouseData->isDrawing;
drawRoi(kMouseData);
break;
case cv::EVENT_LBUTTONUP:
kMouseData->kRectBottomRight = kMouseData->kPointer;
kMouseData->isDrawing = false;
break;
case cv::EVENT_MOUSEMOVE:
kMouseData->kRectBottomRight = kMouseData->kPointer;
drawRoi(kMouseData);
break;
case cv::EVENT_RBUTTONDOWN:
kMouseData->isDrawing = false;
default:
break;
}
}
void selectROI(const std::string& kWiddget, const cv::Mat& kSrcImg, onMouseData& kMouseData)
{
kMouseData.kSrcImg = kSrcImg.clone();
kMouseData.kWiddget = kWiddget;
cv::imshow(kMouseData.kWiddget, kMouseData.kSrcImg);
cv::setMouseCallback(kMouseData.kWiddget,
onMouseCallBack,
reinterpret_cast<void*>(&kMouseData));
cv::waitKey();
}
结果展示
参考资料
- 本文链接: https://www.cnblogs.com/gshang/p/17430031.html
- 版权声明: 本博客所有文章除特别声明外,均采用 CC-BY-NC-SA 4.0 许可协议。转载请注明出处!