摘要:
selectROI在opencv中处于tracking模块,需要opencv_contrib。
由于扣选目标区域在跟踪时候应用较广泛,当没有安装opencv_contrib扩展包时,需要自身去实现该功能。
本文基于c++和python分别实现。可以从左上角往右下角画roi,或者从右下角往左上角画roi。
其中:
- c++代码包括selectROI.h, selectROI.cpp, main.cpp;
- python代码用了大量全局变量,有待改进。
基于c++和opencv实现的selectROI:
selectROI.h
#pragma once
#ifndef _SELECT_ROI_H_HH
#define _SELECT_ROI_H_HH
#include <opencv2/opencv.hpp>
typedef struct selectROI_handler_param {
cv::Point click_1, click_2, click_move;
bool drawRoi;
bool endDraw;
}selectROI_handler_param;
class selectROI_handler
{
friend class selectROI;
protected:
static void onMouse(int event, int x, int y, int flags, void* param);
};
class selectROI {
public:
selectROI();
virtual ~selectROI();
public:
void init_param();
cv::Rect add(const std::string windname, const cv::Mat& image);
void exit();
private:
selectROI_handler_param* param;
};
#endif
selectROI.cpp
#include "selectROI.h"
selectROI::selectROI()
{
}
selectROI::~selectROI()
{
}
void selectROI_handler::onMouse(int event, int x, int y, int flags, void* param)
{
selectROI_handler_param* shparam = (selectROI_handler_param*)param;
switch (event)
{
case CV_EVENT_LBUTTONDOWN:
shparam->drawRoi = true;
shparam->click_1.x = x;
shparam->click_1.y = y;
break;
case CV_EVENT_MOUSEMOVE:
shparam->click_move.x = x;
shparam->click_move.y = y;
break;
case CV_EVENT_LBUTTONUP:
shparam->click_2.x = x;
shparam->click_2.y = y;
shparam->drawRoi = false;
shparam->endDraw = true;
break;
default:
break;
}
}
cv::Rect selectROI::add(const std::string windname, const cv::Mat& image)
{
cv::Mat src_copy = image.clone();
cv::imshow(windname, src_copy);
int lx, ly, w, h;
while (!param->endDraw)
{
cv::setMouseCallback(windname, selectROI_handler::onMouse, param);
src_copy = image.clone();
cv::Rect temp;
if (param->drawRoi)
{
lx = param->click_1.x > param->click_move.x ? param->click_move.x : param->click_1.x;
ly = param->click_1.y > param->click_move.y ? param->click_move.y : param->click_1.y;
w = std::abs(param->click_move.x - param->click_1.x);
h = std::abs(param->click_move.y - param->click_1.y);
temp = cv::Rect(lx, ly, w, h);
cv::rectangle(src_copy, temp, cv::Scalar(255,255,255));
}
cv::imshow(windname, src_copy);
cv::waitKey(20);
}
lx = param->click_1.x > param->click_2.x ? param->click_2.x : param->click_1.x;
ly = param->click_1.y > param->click_2.y ? param->click_2.y : param->click_1.y;
w = std::abs(param->click_2.x - param->click_1.x);
h = std::abs(param->click_2.y - param->click_1.y);
cv::Rect res = cv::Rect(lx, ly, w, h);
return res;
}
void selectROI::init_param()
{
param = new selectROI_handler_param();
memset(param, 0, sizeof(selectROI_handler_param));
param->drawRoi = false;
param->endDraw = false;
}
void selectROI::exit()
{
delete param;
}
main.cpp
#include "selectROI.h"
int main()
{
cv::Mat src = cv::imread("aero3.jpg");
selectROI sRoi;
sRoi.init_param();
cv::Rect roi = sRoi.add("selectRoi.jpg", src);
cv::rectangle(src, roi, cv::Scalar(255, 0, 0));
cv::imshow("selectRoi.jpg", src);
cv::waitKey(0);
sRoi.exit();
return 0;
}
基于python和opencv实现的selectROI
selectROI.py
#--coding--utf8
import cv2 as cv
click_1_x = 0
click_1_y = 0
click_2_x = 0
click_2_y = 0
click_m_x = 0
click_m_y = 0
endDraw = False
drawRoi = False
def lbuttonDown(x):
global drawRoi
global click_1_x
global click_1_y
click_1_x = x[0]
click_1_y = x[1]
drawRoi = True
def mouseMove(x):
global drawRoi
global click_m_x
global click_m_y
if drawRoi == True:
click_m_x = x[0]
click_m_y = x[1]
def lbuttonUp(x):
global drawRoi
global endDraw
global click_2_x
global click_2_y
if drawRoi == True:
click_2_x = x[0]
click_2_y = x[1]
drawRoi = False
endDraw = True
MouseHandler = {
cv.EVENT_LBUTTONDOWN: lbuttonDown,
cv.EVENT_MOUSEMOVE: mouseMove,
cv.EVENT_LBUTTONUP: lbuttonUp
}
def onMouse(event, x, y, flags, param):
t = (x,y)
MouseHandler[event](t)
def add_selectROI(windowName, image):
global endDraw
global drawRoi
global click_m_x
global click_m_y
global click_1_x
global click_1_y
global click_2_x
global click_2_y
src_copy = image.copy()
cv.imshow(windowName, src_copy)
while endDraw == False:
if endDraw == True:
break
cv.setMouseCallback(windowName, onMouse)
src_copy = image.copy()
if drawRoi == True:
cv.rectangle(src_copy, (click_1_x, click_1_y), (click_m_x, click_m_y), (255,255,255))
cv.imshow(windowName, src_copy)
cv.waitKey(20)
return click_1_x,click_1_y,click_2_x,click_2_y
def main():
src = cv.imread('aero3.jpg')
lx,ly,rx,ry = add_selectROI('selectRoi.jpg', src)
cv.rectangle(src, (lx, ly), (rx, ry), (255,0,0))
cv.imshow('selectRoi.jpg', src)
cv.waitKey(0)
if __name__ == "__main__":
main()