검색결과 리스트
글
OpenCV 마우스 이벤트 처리하기
OpenCV에서 마우스를 사용하는 방법입니다. (mouse event handling)
1. 예제 코드
2. 예제 코드 다운로드
3. 실행 예
1. 예제 코드
아래 예는 opencv에서 마우스를 처리하기 위해 필요한 모든 정보를 포함하고 있습니다.
///////////////////////////////////////////////////////////////////////
// OpenCV Mouse event handling example.
// Written by darkpgmr (http://darkpgmr.tistory.com), 2013
#include "stdafx.h"
#include "windows.h"
#include <iostream>
#include "use_opencv.h"
using namespace std;
using namespace cv;
class SampleClass
{
public:
void HandleEvent(int evt, int x, int y, int flags);
};
void SampleClass::HandleEvent(int evt, int x, int y, int flags)
{
if( evt == CV_EVENT_LBUTTONDOWN )
{
cout << "CV_EVENT_LBUTTONDOWN: ";
cout << "x=" << x << ", y=" << y << endl;
}
else if( evt == CV_EVENT_LBUTTONUP )
{
cout << "CV_EVENT_LBUTTONUP: ";
cout << "x=" << x << ", y=" << y << endl;
}
else if( evt == CV_EVENT_MOUSEMOVE )
{
// cout << "CV_EVENT_MOUSEMOVE: ";
// cout << "x=" << x << ", y=" << y << endl;
}
else if( evt == CV_EVENT_RBUTTONDOWN )
{
cout << "CV_EVENT_RBUTTONDOWN: ";
cout << "x=" << x << ", y=" << y << endl;
}
else if( evt == CV_EVENT_RBUTTONUP )
{
cout << "CV_EVENT_RBUTTONUP: ";
cout << "x=" << x << ", y=" << y << endl;
}
else if( evt == CV_EVENT_MBUTTONDOWN )
{
cout << "CV_EVENT_MBUTTONDOWN: ";
cout << "x=" << x << ", y=" << y << endl;
}
else if( evt == CV_EVENT_MBUTTONUP )
{
cout << "CV_EVENT_MBUTTONUP: ";
cout << "x=" << x << ", y=" << y << endl;
}
else if( evt == CV_EVENT_LBUTTONDBLCLK )
{
cout << "CV_EVENT_LBUTTONDBLCLK: ";
cout << "x=" << x << ", y=" << y << endl;
}
else if( evt == CV_EVENT_RBUTTONDBLCLK )
{
cout << "CV_EVENT_RBUTTONDBLCLK: ";
cout << "x=" << x << ", y=" << y << endl;
}
if(flags&CV_EVENT_FLAG_LBUTTON)
{
cout << "\tCV_EVENT_FLAG_LBUTTON" << endl;
}
if(flags&CV_EVENT_FLAG_RBUTTON )
{
cout << "\tCV_EVENT_FLAG_RBUTTON" << endl;
}
if(flags&CV_EVENT_FLAG_MBUTTON )
{
cout << "\tCV_EVENT_FLAG_MBUTTON" << endl;
}
if(flags&CV_EVENT_FLAG_CTRLKEY )
{
cout << "\tCV_EVENT_FLAG_CTRLKEY" << endl;
}
if(flags&CV_EVENT_FLAG_SHIFTKEY )
{
cout << "\tCV_EVENT_FLAG_SHIFTKEY" << endl;
}
if(flags&CV_EVENT_FLAG_ALTKEY )
{
cout << "\tCV_EVENT_FLAG_ALTKEY" << endl;
}
}
void onMouse( int evt, int x, int y, int flags, void* param )
{
SampleClass *p = (SampleClass *)param;
p->HandleEvent(evt, x, y, flags);
}
void proc_video(VideoCapture *vc)
{
SampleClass tmp;
namedWindow("mousekeyboard");
// event handler 등록
setMouseCallback( "mousekeyboard", onMouse, &tmp );
Mat frame;
while(1)
{
*vc >> frame;
if(frame.empty()) break;
imshow("mousekeyboard", frame);
char ch = waitKey(10);
if( ch == 27 ) break; // ESC Key
}
}
int _tmain(int argc, _TCHAR* argv[])
{
//select image source
char data_src;
cout << "1. camera input (640 x 480)\n"
<< "2. camera input (320 x 240)\n"
<< "3. video file input\n"
<< endl
<< "select video source[1-3]: ";
cin >> data_src;
VideoCapture *vc = NULL;
if(data_src=='1')
{
//camera (vga)
vc = new VideoCapture(0);
if (!vc->isOpened())
{
cout << "can't open camera" << endl;
return 0;
}
vc->set(CV_CAP_PROP_FRAME_WIDTH, 640);
vc->set(CV_CAP_PROP_FRAME_HEIGHT, 480);
}
else if(data_src=='2')
{
//camera (qvga)
vc = new VideoCapture(0);
if (!vc->isOpened())
{
cout << "can't open camera" << endl;
return 0;
}
vc->set(CV_CAP_PROP_FRAME_WIDTH, 320);
vc->set(CV_CAP_PROP_FRAME_HEIGHT, 240);
}
else if(data_src=='3')
{
//video (avi)
OPENFILENAME ofn;
char szFile[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = _T("Avi Files(*.avi)\0*.avi\0All Files (*.*)\0*.*\0");
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if(::GetOpenFileName(&ofn)==false) return 0;
vc = new VideoCapture(ofn.lpstrFile);
if (!vc->isOpened())
{
cout << "can't open video file" << endl;
return 0;
}
}
if(vc) proc_video(vc);
if(vc) delete vc;
destroyAllWindows();
return 0;
}
onMouse는 마우스 이벤트를 처리하기 위한 callback 함수로서 함수명은 어떻게 지어도 관계없습니다. onMouse의 인자중 flags는 마우스 이벤트가 발생할 당시의 다른 마우스 버튼들의 상태 및 주요 키보드(shift, ctrl, alt) 상태를 알려줍니다. 마우스 이벤트를 사용하기 위해서는 setMouseCallback 함수를 사용해서 opencv의 namedWindow에 이벤트 핸들러를 등록해 주어야 합니다.
참고사항: 키보드만으로는 이벤트가 발생하지 않습니다. 마우스 이벤트가 발생할 때 부수적으로 주요 키보드 값을 참조할 수 있을 뿐입니다. 일반적인 키보드 이벤트도 같이 처리하고 싶으면 win32(or MFC) 키보드 메시지 처리를 해 주어야 합니다.
2. 예제코드 다운로드
이 예제코드에는 마우스 이벤트 처리 뿐만 아니라 opencv에서 카메라 연결하기, avi 파일 읽어들이는 예제를 포함하고 있습니다. 제가 간단한 opencv 프로그램을 짤 때 주로 사용하는 틀로서 다른 분들에게도 유용할 것으로 생각됩니다.
3. 예제코드 실행 예
by 다크 프로그래머
'프로그래밍 > opencv' 카테고리의 다른 글
OpenCV를 정적 라이브러리(static library)로 사용한 c++ 배포용 프로그램 만들기 (100) | 2013.03.28 |
---|---|
OpenCV 핸드북 (cheatsheet) (63) | 2013.02.27 |
OpenCV 편하게 사용하기 (팁) (26) | 2013.02.13 |
설정
트랙백
댓글
글
라이브 왜곡 보정 프로그램
실시간(라이브)으로 왜곡 보정된 영상을 보여주는 프로그램입니다.
왜곡보정에 관한 이론적인 내용은 [영상처리] - 카메라 왜곡보정 - 이론 및 실제을 참조해 주세요.
프로그램 다운로드 (소스코드 & 샘플동영상 포함)
☞ 포함된 소스코드는 왜곡보정에 관련된 핵심 코드만 포함되어 있습니다. 사용자 인터페이스 및 파일 입출력 등 전체 프로그램 코드는 포함되어 있지 않습니다.
사용법
1. 압축을 풀면 아래 그림과 같이 camera_parameters.txt란 파일이 있는데, 먼저 이 파일을 메모장으로 열어서 카메라 파라미터를 이곳에 적어줍니다. 카메라 캘리브레이션은 [영상처리] - 카메라 캘리브레이션 (Camera Calibration)을 참조하세요.
기본값으로 설정되어 있는 파라미터값은 첨부된 sample.avi 동영상 파일을 획득하는데 사용된 카메라의 파라미터 값입니다.
2. 다음으로 DistortCorrection.exe를 실행시키면 다음과 같이 비디오 소스를 선택할 수 있습니다. 컴퓨터에 연결된 웹캠(webcam)을 사용하려면 1 또는 2를 입력하고, avi 파일을 읽어오려면 3을 입력하고 enter키를 누릅니다.
3. 그러면 아래 그림과 같이 실시간으로 왜곡 보정된 영상을 보여줍니다. 플레이 도중에 SPACE 키를 누르면 동적으로 왜곡 보정 기능을 켜고 끌 수 있습니다.
by 다크 프로그래머
'개발한 것들' 카테고리의 다른 글
걷는 속도와 비를 맞는 양 - 컴퓨터 시뮬레이션 (54) | 2013.06.05 |
---|---|
FFT와 모아레 제거 프로그램 (76) | 2013.01.28 |
오목 (52) | 2013.01.28 |
설정
트랙백
댓글
글
OpenCV 편하게 사용하기 (팁)
1. OpenCV 링크 편하게 하기
2. OpenCV 행렬 원소접근 편하게 하기
3. TypedMat 사용법
1. OpenCV 링크 편하게 하기
OpenCV를 이용한 프로그램을 작성하려면 필요한 헤더화일 및 라이브러리 파일들을 링크시키기 위해 이런 저런 세팅을 해 주어야 합니다.
저는 OpenCV 헤더파일 및 라이브러리 파일들을 다음과 같이 하나의 파일에 모두 넣어놓고 사용합니다 (물론 프로젝트 설정에서 opencv include directory, opencv library directory 는 별도로 설정해 주어야 합니다).
이제 opencv를 사용하고 싶으면 아래 파일만 include하면 ok입니다.
<use_opencv.h>
#ifndef __USE_OPENCV_H__
#define __USE_OPENCV_H__
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/video/video.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/videostab/videostab.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/flann/miniflann.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/ts/ts.hpp"
#include "opencv2/stitching/stitcher.hpp"
#include "opencv2/legacy/legacy.hpp"
#ifdef _DEBUG
#pragma comment(lib,"opencv_core241d.lib")
#pragma comment(lib,"opencv_highgui241d.lib")
#pragma comment(lib,"opencv_imgproc241d.lib")
#pragma comment(lib,"opencv_video241d.lib")
#pragma comment(lib,"opencv_nonfree241d.lib")
#pragma comment(lib,"opencv_videostab241d.lib")
#pragma comment(lib,"opencv_features2d241d.lib")
#pragma comment(lib,"opencv_objdetect241d.lib")
#pragma comment(lib,"opencv_flann241d.lib")
#pragma comment(lib,"opencv_photo241d.lib")
#pragma comment(lib,"opencv_calib3d241d.lib")
#pragma comment(lib,"opencv_ml241d.lib")
#pragma comment(lib,"opencv_contrib241d.lib")
#pragma comment(lib,"opencv_ts241d.lib")
#pragma comment(lib,"opencv_stitching241d.lib")
#pragma comment(lib,"opencv_legacy241d.lib")
#else
#pragma comment(lib,"opencv_core241.lib")
#pragma comment(lib,"opencv_highgui241.lib")
#pragma comment(lib,"opencv_imgproc241.lib")
#pragma comment(lib,"opencv_video241.lib")
#pragma comment(lib,"opencv_nonfree241.lib")
#pragma comment(lib,"opencv_videostab241.lib")
#pragma comment(lib,"opencv_features2d241.lib")
#pragma comment(lib,"opencv_objdetect241.lib")
#pragma comment(lib,"opencv_flann241.lib")
#pragma comment(lib,"opencv_photo241.lib")
#pragma comment(lib,"opencv_calib3d241.lib")
#pragma comment(lib,"opencv_ml241.lib")
#pragma comment(lib,"opencv_contrib241.lib")
#pragma comment(lib,"opencv_ts241.lib")
#pragma comment(lib,"opencv_stitching241.lib")
#pragma comment(lib,"opencv_legacy241.lib")
#endif // _DEBUG
#endif // __USE_OPENCV_H__
2. OpenCV 행렬 원소접근 편하게 하기
저는 opencv를 사용하면서 가장 불편한 점 중의 하나가 행렬(Mat)의 원소를 접근하는 것입니다. 특히나 영상처리를 하다보면 이미지 픽셀 단위로 처리를 할 필요가 있는데 OpenCV가 제공하는 원소 접근 방법(at)은 상당히 불편합니다.
그래서 아래와 같이 Wrapper class를 하나 작성해 보았습니다.
template<class T>
class TypedMat
{
T** m_pData;
int m_nChannels;
int m_nRows, m_nCols;
public:
TypedMat():m_pData(NULL),m_nChannels(1),m_nRows(0),m_nCols(0){}
~TypedMat(){if(m_pData) delete [] m_pData;}
// OpenCV Mat 연동 (메모리 공유)
void Attach(const cv::Mat& m);
void Attach(const IplImage& m);
TypedMat(const cv::Mat& m):m_pData(NULL),m_nChannels(1),m_nRows(0),m_nCols(0) { Attach(m);}
TypedMat(const IplImage& m):m_pData(NULL),m_nChannels(1),m_nRows(0),m_nCols(0) { Attach(m);}
const TypedMat & operator =(const cv::Mat& m){ Attach(m); return *this;}
const TypedMat & operator =(const IplImage& m){ Attach(m); return *this;}
// 행(row) 반환
T* GetPtr(int r)
{ assert(r>=0 && r<m_nRows); return m_pData[r];}
// 연산자 중첩 (원소접근) -- 2D
T * operator [](int r)
{ assert(r>=0 && r<m_nRows); return m_pData[r];}
const T * operator [](int r) const
{ assert(r>=0 && r<m_nRows); return m_pData[r];}
// 연산자 중첩 (원소접근) -- 3D
T & operator ()(int r, int c, int k)
{ assert(r>=0 && r<m_nRows && c>=0 && c<m_nCols && k>=0 && k<m_nChannels); return m_pData[r][c*m_nChannels+k];}
const T operator ()(int r, int c, int k) const
{ assert(r>=0 && r<m_nRows && c>=0 && c<m_nCols && k>=0 && k<m_nChannels); return m_pData[r][c*m_nChannels+k];}
};
template<class T>
void TypedMat<T>::Attach(const cv::Mat& m)
{
assert(sizeof(T)==m.elemSize1());
m_nChannels = m.channels();
m_nRows = m.rows;
m_nCols = m.cols;
if(m_pData) delete [] m_pData;
m_pData = new T * [m_nRows];
for(int r=0; r<m_nRows; r++)
{
m_pData[r] = (T *)(m.data + r*m.step);
}
}
template<class T>
void TypedMat<T>::Attach(const IplImage& m)
{
assert(sizeof(T) == m.widthStep/(m.width*m.nChannels));
m_nChannels = m.nChannels;
m_nRows = m.height;
m_nCols = m.width;
if(m_pData) delete [] m_pData;
m_pData = new T * [m_nRows];
for(int r=0; r<m_nRows; r++)
{
m_pData[r] = (T *)(m.imageData + r*m.widthStep);
}
}
3. TypedMat 사용법
메모리를 공유하기 때문에 추가적인 연산 로드는 거의 없습니다. IplImage, cv::Mat을 지원합니다. 사용법은 다음과 같습니다.
* 이미지의 경우
#include "use_opencv.h"
Mat image;
TypedMat<unsigned char> tm = image; // 연결방법 1
TypedMat<unsigned char> tm; tm = image; // 연결방법 2
TypedMat<unsigned char> tm; tm.Attach(image); // 연결방법 3
// image가 1채널 grayscale 이미지일 경우
tm[y][x] = 100; // (x,y)의 픽셀값을 100으로 설정
// image가 3채널 color 이미지일 경우
tm(y,x,0) = 100; // (x,y)의 픽셀의 blue값을 100으로 설정
tm(y,x,1) = 200; // (x,y)의 픽셀의 green값을 200으로 설정
tm(y,x,2) = 50; // (x,y)의 픽셀의 red값을 50으로 설정
* 2D float 타입 행렬의 경우
#include "use_opencv.h"
Mat f_image;
TypedMat<float> fm = f_image;
fm[y][x] = 3.12f;
by 다크 프로그래머
'프로그래밍 > opencv' 카테고리의 다른 글
OpenCV를 정적 라이브러리(static library)로 사용한 c++ 배포용 프로그램 만들기 (100) | 2013.03.28 |
---|---|
OpenCV 핸드북 (cheatsheet) (63) | 2013.02.27 |
OpenCV 마우스 이벤트 처리하기 (9) | 2013.02.14 |