【画像処理】selectROI実装

34242 ワード

要旨: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 
    
    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()