OpenCV常用图像操作和鼠标操作

85 篇文章 4 订阅

最近的工作经常需要对图像进行操作,也需要用鼠标对图像进行各种操作,于是自己整理和编写了这个类,总结了常用的基于OpenCV对图像进行的操作。

这个类我也将继续完善和丰富下去,需要的朋友可以直接使用。

如果有什么疏漏的地方还请多多指教。

 

首先是头文件:

 

/* ******* ccv.h **********
********* opencv常用操作函数声明 ********** */

/* author: autumoon */

#ifndef _CCV_H_
#define _CCV_H_

#include <afxdlgs.h> //打开文件

#include "cv.h"
#include "cxcore.h"
#include "highgui.h"  
using namespace cv;

#define SCREEN_WIDTH     1920
#define SCREEN_HEIGHT    1080

class CCvImage
{
public:
	Mat m_Minput; //使用Mat类型

	//鼠标控制相关变量
	Mat m_Mmask;
	Mat m_Mmid;
	Mat m_Msrc; //外部矩阵输入
	char* m_szTitle;
	CvPoint m_curr_pt;
	CvPoint m_prev_pt;
	CvRect m_rect;
	float m_fProportion;
	int m_nThick;

public:
	CCvImage();
	CCvImage(Mat mat);
	CCvImage(IplImage* pImage);
	CCvImage(char szImgPath[], int flags = 1);
	CCvImage(CString strImgPath, int flags = 1);

public:
	//图像操作
	int AutoSizeMat(Mat& Msrc, Mat& Mdst, float& fProportion, int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT);
	int ShowImg(char szTitle[] = "显示图像", bool bAutoClose = true);
	int ShowImg(Mat Msrc, char szTitle[] = "显示图像", bool bAutoClose = true); //显示某个矩阵
	int ShowImgAutoSize(char szTitle[] = "显示图像", int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT,  bool bAutoClose = true);
	int ShowImgAutoSize(Mat Msrc, char szTitle[] = "显示图像", int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT,  bool bAutoClose = true);

	//鼠标图像操作
	int DrawCurveOnImg(Mat Msrc, char* szTitle = "画曲线", int nThick = 2);
	int DrawCurveOnBigImg(Mat Msrc, int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT, char* szTitle = "画曲线", int nThick = 2);
	int DrawLineOnImg(Mat Msrc, CvPoint& pStart, CvPoint& pEnd, char* szTitle = "画直线", int nThick = 2);
	int DrawLineOnBigImg(Mat Msrc, CvPoint& pStart, CvPoint& pEnd, int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT, char* szTitle = "画直线", int nThick = 2);
	int DrawRectOnImg(Mat Msrc, CvRect& rect, char* szTitle = "画矩形", int nThick = 2);
	int DrawRectOnBigImg(Mat Msrc, CvRect& rect, int nScreenWidth = SCREEN_WIDTH, int nScreenHeight = SCREEN_HEIGHT, char* szTitle = "画矩形", int nThick = 2);
	int GetMaskByCurve(Mat Msrc, Mat& pDst, char* szTitle = "获取遮罩"); //通过曲线获取遮罩
	int GetMaskByDaub(Mat Msrc, Mat& pDst, int nRadius = 20, char* szTitle = "获取遮罩"); //通过涂抹获取遮罩

	//其他操作
	int ResizeCvPoint(CvPoint& Csrc, float fProportion);
	int ResizeCvRect(CvRect& Csrc, float fProportion);

private:
	IplImage* IInput; //内部使用的IplImage指针
};

//回调函数
void on_mouse_curve(int event, int x, int y, int flags, void* pParameters);
void on_mouse_big_curve(int event, int x, int y, int flags, void* pParameters);
void on_mouse_curve_mask(int event, int x, int y, int flags, void* pParameters);
void on_mouse_daub(int event, int x, int y, int flags, void* pParameters);
void on_mouse_line(int event, int x, int y, int flags, void* pParameters);
void on_mouse_rect(int event, int x, int y, int flags, void* pParameters);

#endif


然后是cpp文件:

 

 

/* ******* ccv.cpp **********
********* opencv常用操作函数实现 ********** */

/* author: autumoon */

#include "ccv.h"

CCvImage::CCvImage()
{
	m_rect = cvRect(-1, -1, -1, -1);
	IInput = NULL;
}

CCvImage::CCvImage(char szImgPath[], int flags/* = 1*/)
{
	m_rect = cvRect(-1, -1, -1, -1);
	IInput = NULL;

	m_Minput = imread(szImgPath, flags);
}

CCvImage::CCvImage(CString strImgPath, int flags/* = 1*/)
{
	m_rect = cvRect(-1, -1, -1, -1);
	IInput = NULL;

	char* szImgPath;

#ifdef _UNICODE
	USES_CONVERSION;
	szImgPath = W2A(strCstring);
#else
	szImgPath = (LPSTR)(LPCTSTR)strImgPath;
#endif

	m_Minput = imread(szImgPath, flags);
}

int CCvImage::AutoSizeMat(Mat& Msrc, Mat& Mdst, float& fProportion, int nScreenWidth/* = SCREEN_WIDTH*/, int nScreenHeight/* = SCREEN_HEIGHT*/)
{
	if (Msrc.cols <= nScreenWidth && Msrc.rows <= nScreenHeight)
	{
		Msrc.copyTo(Mdst);
		fProportion = 1.0;

		return 0;
	}

	if ((float)Msrc.cols / Msrc.rows >= (float)nScreenWidth / nScreenWidth)
	{
		fProportion = (float)Msrc.cols / nScreenWidth;
	}
	else
	{
		fProportion = (float)Msrc.rows / nScreenHeight;
	}

	resize(Msrc, Mdst, cv::Size(Msrc.cols / fProportion, Msrc.rows / fProportion));

	return 0;
}

int CCvImage::ShowImg(char szTitle[]/* = "显示图像"*/, bool bAutoClose/* = true*/)
{
	imshow(szTitle, m_Minput);
	waitKey();
	if (bAutoClose)
	{
		destroyWindow(szTitle);
	}
	return 0;
}

int CCvImage::ShowImg(Mat Msrc, char szTitle[]/* = "显示图像"*/, bool bAutoClose/* = true*/)
{
	imshow(szTitle, Msrc);
	waitKey();
	if (bAutoClose)
	{
		destroyWindow(szTitle);
	}
	return 0;
}

int CCvImage::ShowImgAutoSize(char szTitle[]/* = "显示图像"*/, int nScreenWidth/* = 1920*/, int nScreenHeight/* = 1080*/, bool bAutoClose/* = true*/)
{
	Mat Mresize;
	float fProportion;
	AutoSizeMat(m_Minput, Mresize, fProportion, nScreenWidth, nScreenHeight);

	imshow(szTitle, Mresize);
	waitKey();

	if (bAutoClose)
	{
		destroyWindow(szTitle);
	}

	return 0;
}

int CCvImage::ShowImgAutoSize(Mat Msrc, char szTitle[]/* = "显示图像"*/, int nScreenWidth/* = 1920*/, int nScreenHeight/* = 1080*/, bool bAutoClose/* = true*/)
{
	Mat Mresize;
	float fProportion;
	AutoSizeMat(Msrc, Mresize, fProportion, nScreenWidth, nScreenHeight);

	imshow(szTitle, Mresize);
	waitKey();
	if (bAutoClose)
	{
		destroyWindow(szTitle);
	}

	return 0;
}

int CCvImage::DrawCurveOnImg(Mat Msrc, char* szTitle/* = "画曲线"*/, int nThick/* = 2*/)
{
	m_Mmid.release();
	m_Mmid = Msrc;
	//显示原图
	imshow(szTitle,m_Mmid);

	//鼠标回调函数
	this->m_szTitle = szTitle;
	this->m_nThick = nThick;
	cvSetMouseCallback(szTitle, on_mouse_curve, this);
	waitKey(0);

	destroyWindow(szTitle);

	return 0;
}

void on_mouse_curve(int event, int x, int y, int flags, void* pParameters)
{
	CCvImage* pthis = (CCvImage*)pParameters;

	//获取相关的参数
	char* szTitle = pthis->m_szTitle;
	CvPoint& prev_pt = pthis->m_prev_pt;
	int nThick = pthis->m_nThick;
	Mat& Mmid = pthis->m_Mmid;

	if(!Mmid.data)
		return;

	if ( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))  //判断事件为松开鼠标左键或者不是左拖拽
	{
		prev_pt = cvPoint(-1, -1);
	}
	else if (event == CV_EVENT_LBUTTONDOWN)  //判断为按下左键
	{
		prev_pt = cvPoint(x,y);
	}
	else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))  //判断移动鼠标并且左拖拽
	{
		CvPoint pt = cvPoint(x, y);
		if ( prev_pt.x < 0)
		{
			prev_pt = pt;
		}
		line(Mmid, prev_pt, pt, Scalar::all(255), nThick ,8,0); //原图上划线
		prev_pt = pt;
		imshow(szTitle, Mmid);
	}

	if (event == CV_EVENT_RBUTTONUP)
	{
		destroyWindow(szTitle);
	}
}

int CCvImage::DrawCurveOnBigImg(Mat Msrc,
	int nScreenWidth/* = SCREEN_WIDTH*/, int nScreenHeight/* = SCREEN_HEIGHT*/, char* szTitle/* = "画曲线"*/, int nThick/* = 2*/)
{
	m_Mmid.release();
	m_Msrc.release();
	float fProportion;
	AutoSizeMat(Msrc, m_Mmid, fProportion, nScreenWidth, nScreenHeight);
	m_Msrc = Msrc;

	//显示原图
	imshow(szTitle, m_Mmid);

	//鼠标回调函数
	this->m_szTitle = szTitle;
	this->m_nThick = nThick;
	this->m_fProportion = fProportion;
	cvSetMouseCallback(szTitle, on_mouse_big_curve, this);
	waitKey(0);

	destroyWindow(szTitle);

	return 0;
}

void on_mouse_big_curve(int event, int x, int y, int flags, void* pParameters)
{
	CCvImage* pthis = (CCvImage*)pParameters;

	//获取相关的参数
	char* szTitle = pthis->m_szTitle;
	CvPoint& prev_pt = pthis->m_prev_pt;
	int nThick = pthis->m_nThick;
	Mat& Mmid = pthis->m_Mmid;

	if(!Mmid.data)
		return;

	if ( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))  //判断事件为松开鼠标左键或者不是左拖拽
	{
		prev_pt = cvPoint(-1, -1);
	}
	else if (event == CV_EVENT_LBUTTONDOWN)  //判断为按下左键
	{
		prev_pt = cvPoint(x,y);
	}
	else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))  //判断移动鼠标并且左拖拽
	{
		CvPoint pt = cvPoint(x, y);
		if ( prev_pt.x < 0)
		{
			prev_pt = pt;
		}
		line(Mmid, prev_pt, pt, Scalar::all(255), nThick ,8,0); //缩小图上划线

		CvPoint t_prev_pt = prev_pt, t_pt = pt;
		pthis->ResizeCvPoint(t_prev_pt, pthis->m_fProportion);
		pthis->ResizeCvPoint(t_pt, pthis->m_fProportion);
		line(pthis->m_Msrc, t_prev_pt, t_pt, Scalar::all(255), nThick ,8,0); //原图上划线
		prev_pt = pt;
		imshow(szTitle, Mmid);
	}

	if (event == CV_EVENT_RBUTTONUP)
	{
		destroyWindow(szTitle);
	}
}

int CCvImage::DrawLineOnImg(Mat Msrc, CvPoint& pStart, CvPoint& pEnd, char* szTitle/* = "画直线"*/, int nThick/* = 2*/)
{
	m_Mmid.release();
	Msrc.copyTo(m_Mmid);
	//显示原图
	imshow(szTitle, m_Mmid);

	//鼠标回调函数
	this->m_szTitle = szTitle;
	this->m_nThick = nThick;
	cvSetMouseCallback(szTitle, on_mouse_line, this);
	waitKey(0);

	pStart = m_prev_pt;
	pEnd = m_curr_pt;
	destroyWindow(szTitle);

	return 0;
}

int CCvImage::DrawLineOnBigImg(Mat Msrc, CvPoint& pStart, CvPoint& pEnd,
	int nScreenWidth/* = SCREEN_WIDTH*/, int nScreenHeight/* = SCREEN_HEIGHT*/, char* szTitle/* = "画直线"*/, int nThick/* = 2*/)
{
	m_Mmid.release();
	float fProportion;
	AutoSizeMat(Msrc, m_Mmid, fProportion, nScreenWidth, nScreenHeight);
	//显示原图
	imshow(szTitle, m_Mmid);

	//鼠标回调函数
	this->m_szTitle = szTitle;
	this->m_nThick = nThick;
	cvSetMouseCallback(szTitle, on_mouse_line, this);
	waitKey(0);

	pStart = m_prev_pt;
	pEnd = m_curr_pt;
	ResizeCvPoint(pStart, fProportion);
	ResizeCvPoint(pEnd, fProportion);

	destroyWindow(szTitle);

	return 0;
}

void on_mouse_line(int event, int x, int y, int flags, void* pParameters)
{
	CCvImage* pthis = (CCvImage*)pParameters;

	//获取相关的参数
	char* szTitle = pthis->m_szTitle;
	CvPoint curr_pt;
	CvPoint prev_pt = pthis->m_prev_pt; //注意这里不是引用
	int nThick = pthis->m_nThick;
	Mat& Mmid = pthis->m_Mmid;

	if(!Mmid.data)
		return;

	Mat Mori;

	if ( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))  //判断事件为松开鼠标左键或者不是左拖拽
	{
		prev_pt = cvPoint(-1, -1);
	}
	else if (event == CV_EVENT_LBUTTONDOWN)  //判断为按下左键
	{
		prev_pt = cvPoint(x,y);
	}
	else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))  //判断移动鼠标并且左拖拽
	{
		CvPoint pt = cvPoint(x, y);
		if ( prev_pt.x < 0)
		{
			prev_pt = pt;
		}
		Mori.release();
		Mmid.copyTo(Mori);
		line(Mori, prev_pt, pt, Scalar::all(255), nThick ,8,0); //原图上划线
		curr_pt = pt;
		pthis->m_prev_pt = prev_pt;
		pthis->m_curr_pt = pt;
		imshow(szTitle, Mori);
	}

	if (event == CV_EVENT_RBUTTONUP)
	{
		destroyWindow(szTitle);
	}
}

int CCvImage::DrawRectOnImg(Mat Msrc, CvRect& rect, char* szTitle/* = "画矩形"*/, int nThick/* = 2*/)
{
	m_Mmid.release();
	Msrc.copyTo(m_Mmid);

	//显示原图
	imshow(szTitle,m_Mmid);

	//鼠标回调函数
	this->m_szTitle = szTitle;
	this->m_nThick = nThick;
	cvSetMouseCallback(szTitle, on_mouse_rect, this);
	waitKey(0);

	destroyWindow(szTitle);

	rect = this->m_rect;

	return 0;
}

int CCvImage::DrawRectOnBigImg(Mat Msrc, CvRect& rect,
	int nScreenWidth/* = SCREEN_WIDTH*/, int nScreenHeight/* = SCREEN_HEIGHT*/, char* szTitle/* = "画矩形"*/, int nThick/* = 2*/)
{
	m_Mmid.release();
	float fProportion;
	AutoSizeMat(Msrc, m_Mmid, fProportion, nScreenWidth, nScreenHeight);

	//显示原图
	imshow(szTitle,m_Mmid);

	//鼠标回调函数
	this->m_szTitle = szTitle;
	this->m_nThick = nThick;
	cvSetMouseCallback(szTitle, on_mouse_rect, this);
	waitKey(0);

	destroyWindow(szTitle);

	rect = this->m_rect;
	ResizeCvRect(rect, fProportion);

	return 0;
}

void on_mouse_rect(int event, int x, int y, int flags, void* pParameters)
{
	CCvImage* pthis = (CCvImage*)pParameters;

	//获取相关的参数
	char* szTitle = pthis->m_szTitle;
	CvPoint& prev_pt = pthis->m_prev_pt;
	CvRect& rect = pthis->m_rect;
	int nThick = pthis->m_nThick;
	Mat& Mmid = pthis->m_Mmid;

	if(!Mmid.data)
		return;

	Mat Mori;

	if ( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))  //判断事件为松开鼠标左键或者不是左拖拽
	{
		prev_pt = cvPoint(-1, -1);
	}
	else if (event == CV_EVENT_LBUTTONDOWN)  //判断为按下左键
	{
		prev_pt = cvPoint(x,y);
	}
	else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))  //判断移动鼠标并且左拖拽
	{
		CvPoint pt = cvPoint(x, y);
		if ( prev_pt.x < 0)
		{
			prev_pt = pt;
		}
		Mori.release();
		Mmid.copyTo(Mori);
		rectangle(Mori, prev_pt, pt, Scalar::all(255), nThick);
		rect = cvRect(prev_pt.x, prev_pt.y, pt.x - prev_pt.x, pt.y - prev_pt.y);
		imshow(szTitle, Mori);
	}

	if (event == CV_EVENT_RBUTTONUP)
	{
		destroyWindow(szTitle);
	}
}

int CCvImage::GetMaskByCurve(Mat Msrc, Mat& Mdst, char* szTitle/* = "获取遮罩"*/)
{
	m_Mmid.release();
	Msrc.copyTo(m_Mmid);

	Mat mask(Msrc.rows, Msrc.cols, CV_8U, Scalar(255));
	m_Mmask.release();
	m_Mmask = mask;

	//显示原图
	imshow(szTitle,m_Mmid);

	//鼠标回调函数
	this->m_szTitle = szTitle;
	cvSetMouseCallback(szTitle, on_mouse_curve_mask, this);
	waitKey(0);

	m_Mmask.copyTo(Mdst);
	destroyWindow(szTitle);

	return 0;
}

void on_mouse_curve_mask(int event, int x, int y, int flags, void* pParameters)
{
	CCvImage* pthis = (CCvImage*)pParameters;

	//获取相关的参数
	char* szTitle = pthis->m_szTitle;
	CvPoint& prev_pt = pthis->m_prev_pt;
	CvRect& rect = pthis->m_rect;
	Mat& Mmid = pthis->m_Mmid;
	Mat& Mmask = pthis->m_Mmask;

	if(!Mmid.data)
		return;

	if ( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))  //判断事件为松开鼠标左键或者不是左拖拽
	{
		prev_pt = cvPoint(-1, -1);
	}
	else if (event == CV_EVENT_LBUTTONDOWN)  //判断为按下左键
	{
		prev_pt = cvPoint(x,y);
	}
	else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))  //判断移动鼠标并且左拖拽
	{
		CvPoint pt = cvPoint(x, y);
		if ( prev_pt.x < 0)
		{
			prev_pt = pt;
		}
		line(Mmask, prev_pt, pt, Scalar(0),2,8,0); //模板上划线
		line(Mmid, prev_pt, pt, Scalar::all(255),2,8,0);          //原图上划线
		prev_pt = pt;
		imshow(szTitle, Mmid);
	}
	if (event == CV_EVENT_RBUTTONUP)
	{
		floodFill(Mmask, Point(x,y), Scalar(0));//填充抠图模板
	}
}

int CCvImage::GetMaskByDaub(Mat Msrc, Mat& Mdst, int nRadius/* = 20*/, char* szTitle/* = "获取遮罩"*/)
{
	m_Mmid.release();
	Msrc.copyTo(m_Mmid);

	Mat mask(Msrc.rows, Msrc.cols, CV_8U, Scalar(0));
	m_Mmask.release();
	m_Mmask = mask;

	//显示原图
	imshow(szTitle,m_Mmid);

	//鼠标回调函数
	this->m_szTitle = szTitle;
	this->m_nThick = nRadius;
	cvSetMouseCallback(szTitle, on_mouse_daub, this);
	waitKey(0);

	m_Mmask.copyTo(Mdst);
	destroyWindow(szTitle);

	return 0;
}

void on_mouse_daub(int event, int x, int y, int flags, void* pParameters)
{
	CCvImage* pthis = (CCvImage*)pParameters;

	//获取相关的参数
	char* szTitle = pthis->m_szTitle;
	CvPoint& prev_pt = pthis->m_prev_pt;
	int nThick = pthis->m_nThick;
	Mat& Mmid = pthis->m_Mmid;

	if(!Mmid.data)
		return;

	if ( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))  //判断事件为松开鼠标左键或者不是左拖拽
	{
		prev_pt = cvPoint(-1, -1);
	}
	else if (event == CV_EVENT_LBUTTONDOWN)  //判断为按下左键
	{
		prev_pt = cvPoint(x,y);
	}
	else if ( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))  //判断移动鼠标并且左拖拽
	{
		CvPoint pt = cvPoint(x, y);
		if ( prev_pt.x < 0)
		{
			prev_pt = pt;
		}
		line(pthis->m_Mmask, prev_pt, pt, Scalar(255), nThick, 8, 0); //模板上划线
		line(Mmid, prev_pt, pt, Scalar::all(255), nThick, 8, 0);          //原图上划线
		prev_pt = pt;
		imshow(szTitle, Mmid);
	}

	if (event == CV_EVENT_RBUTTONUP)
	{
		destroyWindow(szTitle);
	}
}

int CCvImage::ResizeCvPoint(CvPoint& Csrc, float fProportion)
{
	Csrc.x *= fProportion;
	Csrc.y *= fProportion;

	return 0;
}

int CCvImage::ResizeCvRect(CvRect& Csrc, float fProportion)
{
	Csrc.x *= fProportion;
	Csrc.y *= fProportion;
	Csrc.width *= fProportion;
	Csrc.height *= fProportion;

	return 0;
}

 

如果我的文章对你有帮助,欢迎留言支持我。

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值