Исправлена работа детекторов граней. Устранена утечка памяти. Обработка выполняется в новом потоке. Пункт "Устройства" изменён на "Пауза". Добавлено диалоговое окно "О программе".

This commit is contained in:
Victor 2012-04-06 01:17:36 +03:00
parent 5634f98ec3
commit 3e57fbb9d2
11 changed files with 152 additions and 42 deletions

View File

@ -5,17 +5,23 @@
*/
IplImage* AbstractOperator::applyOperator(IplImage* sourceImage) {
IplImage* horizontalEdges = cvCloneImage(sourceImage);
CvMat* horizontalMatrix = getHorizontalKernelMatrix();
cvFilter2D(sourceImage, horizontalEdges, horizontalMatrix, cvPoint(-1,-1));
cvReleaseMat(&horizontalMatrix);
IplImage* verticalEdges = cvCloneImage(sourceImage);
CvMat* verticalMatrix = getVerticalKernelMatrix();
cvFilter2D(sourceImage, verticalEdges, verticalMatrix, cvPoint(-1,-1));
cvReleaseMat(&verticalMatrix);
sourceImage = applyGradient(horizontalEdges, verticalEdges);
return sourceImage;
horizontalEdges = applyGradient(horizontalEdges, verticalEdges);
cvReleaseImage(&sourceImage);
cvReleaseImage(&verticalEdges);
return horizontalEdges;
}
/**
* Создать матрицы свертки.
**/
void AbstractOperator::createMatrix() {
createHorizontalKernelMatrix();
createVerticalKernelMatrix();
}
/**
@ -25,7 +31,7 @@ CvMat* AbstractOperator::setupKernelMatrixFromArray(CvMat* kernel, float* matrix
int w = kernel->width;
for (int y = 0; y < kernel->height; y++) {
for (int x = 0; x < w; x++) {
cvSet2D(kernel, 0, 0, cvRealScalar(matrix[y*w+x]));
cvSet2D(kernel, y, x, cvRealScalar(matrix[y*w+x]));
}
}
return kernel;
@ -40,6 +46,7 @@ IplImage* AbstractOperator::applyGradient(IplImage* horiz, IplImage* vert) {
// Вычисляем значения для каждого канала
for (int i = 0; i < ch; i++) {
pHor[ch*x+i] = calculateGradient(pHor[ch*x+i], pVert[ch*x+i]);
if (pHor[ch*x+i] > 255) pHor[ch*x+i] = 255;
}
}
}

View File

@ -8,16 +8,19 @@
class AbstractOperator {
public:
IplImage* applyOperator(IplImage* sourceImage);
void createMatrix();
protected:
virtual CvMat* getHorizontalKernelMatrix() = 0;
virtual CvMat* getVerticalKernelMatrix() = 0;
virtual void createHorizontalKernelMatrix() = 0;
virtual void createVerticalKernelMatrix() = 0;
CvMat* setupKernelMatrixFromArray(CvMat* sourceMatrix, float* matrix);
protected:
CvMat* horizontalMatrix;
CvMat* verticalMatrix;
private:
IplImage* applyGradient(IplImage* horizontalEdges, IplImage* verticalEdges);
uchar calculateGradient(uchar pix1, uchar pix2);
int numberOfChannels;
};

View File

@ -17,6 +17,7 @@
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
#pragma code_page(1251)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
@ -54,7 +55,7 @@ BEGIN
POPUP "&Камера"
BEGIN
MENUITEM "&Захват кадра\tF9", ID_SNAPSHOT
MENUITEM "У&стройство", ID_DEVICE
MENUITEM "&Пауза\tCtrl+P", ID_PAUSE
MENUITEM SEPARATOR
MENUITEM "Вы&ход\tAlt+F4", ID_EXIT
END
@ -82,16 +83,63 @@ END
IDR_MAINACCELERATOR ACCELERATORS
BEGIN
"1", ID_OP_ROBERTS, VIRTKEY, NOINVERT
"2", ID_OP_PREWITT, VIRTKEY, NOINVERT
"3", ID_OP_SOBEL, VIRTKEY, NOINVERT
"G", ID_EF_GRAYSCALE, VIRTKEY, CONTROL, NOINVERT
"I", ID_EF_INVERSE, VIRTKEY, CONTROL, NOINVERT
"O", ID_EF_ORIGINAL, VIRTKEY, CONTROL, NOINVERT
VK_F9, ID_SNAPSHOT, VIRTKEY, NOINVERT
VK_F4, ID_EXIT, VIRTKEY, ALT, NOINVERT
"2", ID_OP_PREWITT, VIRTKEY, NOINVERT
"1", ID_OP_ROBERTS, VIRTKEY, NOINVERT
"3", ID_OP_SOBEL, VIRTKEY, NOINVERT
VK_F9, ID_SNAPSHOT, VIRTKEY, NOINVERT
"P", ID_PAUSE, VIRTKEY, CONTROL, NOINVERT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUT_DIALOG DIALOGEX 0, 0, 203, 86
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "О программе"
FONT 8, "Tahoma", 0, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDC_OK,73,65,61,14,BS_CENTER
LTEXT "Автор: Виктор aNNiMON Мельник",-1,43,20,113,8,NOT WS_GROUP
LTEXT "DonNUEdgeDetector 1.0",-1,55,7,82,9,NOT WS_GROUP
LTEXT "Исходный код открыт и располагается на:",-1,29,33,149,9,NOT WS_GROUP
PUSHBUTTON "github.com/aNNiMON/DonNUEdgeDetector",IDC_GO_TO_GIT,22,45,163,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUT_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 9
RIGHTMARGIN, 197
TOPMARGIN, 7
BOTTOMMARGIN, 79
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "icon.ico"
#endif // Русский (Россия) resources
/////////////////////////////////////////////////////////////////////////////

View File

@ -8,6 +8,7 @@ EdgeDetector::EdgeDetector() {}
*/
EdgeDetector::~EdgeDetector() {
cvReleaseCapture(&camera);
cvReleaseImage(&resultFrame);
cvDestroyAllWindows();
delete edgeDetectOperator;
}
@ -27,20 +28,25 @@ void EdgeDetector::init(int deviceNumber) {
void EdgeDetector::update() {
if (camera == NULL) return;
cvWaitKey(33);
cameraFrame = cvQueryFrame(camera);
resultFrame = cvCloneImage(cameraFrame);
cvReleaseImage(&resultFrame);
if (isGrayScaleEffect) {
IplImage* tempFrame = cvCloneImage(resultFrame);
IplImage* tempFrame = cvCloneImage(cameraFrame);
resultFrame = cvCreateImage(imageSize, cameraFrame->depth, CV_LOAD_IMAGE_GRAYSCALE);
cvCvtColor(tempFrame, resultFrame, CV_BGR2GRAY);
}
cvReleaseImage(&tempFrame);
} else resultFrame = cvCloneImage(cameraFrame);
if (!isOriginalEffect) {
resultFrame = edgeDetectOperator->applyOperator(resultFrame);
}
if (isInverseEffect) {
IplImage* tempFrame = cvCloneImage(resultFrame);
cvNot(tempFrame, resultFrame);
cvReleaseImage(&tempFrame);
}
cvShowImage(getWindowName(), resultFrame);
@ -86,11 +92,11 @@ void EdgeDetector::setOperator(UINT typeOperator) {
edgeDetectOperator = new SobelOperator();
break;
}
edgeDetectOperator->createMatrix();
}
CvCapture* EdgeDetector::initCamera(int deviceNumber) {
//return cvCreateCameraCapture(deviceNumber);
return cvCaptureFromCAM(deviceNumber);
}

View File

@ -1,6 +1,7 @@
#include <windows.h>
#include <stdio.h>
#include <commctrl.h>
#include <process.h>
#include "EdgeDetector.h"
#include "WindowClass.h"
#include "Window.h"
@ -10,6 +11,7 @@
LRESULT CALLBACK mainWindowProcedure(HWND, UINT, UINT, LONG);
void menuCommandSelected(HWND hWnd, UINT wParam);
void setPause(HWND hWnd, bool pause);
void setOperatorType(HWND hWnd, UINT type);
void setEffectTypes(HWND hWnd);
@ -18,6 +20,7 @@ bool effectsEnabled[EFFECTS_END - EFFECTS_START + 1];
/** Детектор границ */
EdgeDetector detector;
bool pause, runningThread;
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) {
// Регистрация класса окна
@ -25,6 +28,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmd
wClass.setToDefault();
wClass.setInstance(hInstance);
wClass.setClassName(L"DonNUEdgeDetector");
wClass.setIconType(MAKEINTRESOURCE(IDI_ICON1));
wClass.setMenuName(MAKEINTRESOURCE(IDR_MAINMENU));
wClass.setWindowProcedure(mainWindowProcedure);
if (!wClass.registerClass()) return 0;
@ -49,7 +53,6 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmd
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)) {
detector.update();
if(!TranslateAccelerator(wnd.getWindow(), hAccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
@ -58,6 +61,14 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmd
return msg.wParam;
}
VOID edgeDetectingThread (PVOID pvoid) {
while (runningThread) {
if (!pause) detector.update();
}
_endthread();
}
/**
* Оконная процедура.
*/
@ -65,8 +76,11 @@ LRESULT CALLBACK mainWindowProcedure(HWND hWnd, UINT message, UINT wParam, LONG
switch(message) {
case WM_CREATE:
runningThread = true;
setPause(hWnd, false);
setOperatorType(hWnd, ID_OP_ROBERTS);
setEffectTypes(hWnd);
_beginthread(edgeDetectingThread, 0, NULL) ;
break;
case WM_COMMAND:
@ -74,6 +88,7 @@ LRESULT CALLBACK mainWindowProcedure(HWND hWnd, UINT message, UINT wParam, LONG
break;
case WM_DESTROY:
runningThread = false;
PostQuitMessage(0);
break;
@ -83,6 +98,27 @@ LRESULT CALLBACK mainWindowProcedure(HWND hWnd, UINT message, UINT wParam, LONG
return 0;
}
/**
* Обработка сообщений диалогового окна "О программе"
*/
BOOL CALLBACK AboutDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDC_GO_TO_GIT:
ShellExecuteA(GetParent(hDlg), "open", "https://github.com/aNNiMON/DonNUEdgeDetector", NULL, NULL, SW_MAXIMIZE);
return TRUE;
case IDC_OK:
EndDialog(hDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
/**
* Обработка события выбранного пункта меню.
*/
@ -94,7 +130,8 @@ void menuCommandSelected(HWND hWnd, UINT wParam) {
detector.snapshot();
break;
case ID_DEVICE:
case ID_PAUSE:
setPause(hWnd, !pause);
break;
case ID_OP_ROBERTS:
@ -111,6 +148,7 @@ void menuCommandSelected(HWND hWnd, UINT wParam) {
break;
case ID_ABOUT:
DialogBox(NULL, MAKEINTRESOURCE(IDD_ABOUT_DIALOG), hWnd, (DLGPROC)AboutDialogProc);
break;
case ID_EXIT:
@ -119,6 +157,15 @@ void menuCommandSelected(HWND hWnd, UINT wParam) {
}
}
/**
* Приостановить работу детектора граней.
*/
void setPause(HWND hWnd, bool _pause) {
pause = _pause;
HMENU cameraMenu = GetSubMenu(GetMenu(hWnd), 0);
ULONG check = pause ? MF_CHECKED : MF_UNCHECKED;
CheckMenuItem(cameraMenu, 1, check);
}
/**
* Установить тип оператора (ID_OP_ROBERTS, ID_OP_SOBEL, ID_OP_PREWITT);

View File

@ -4,20 +4,20 @@
class PrewittOperator : public AbstractOperator {
public:
CvMat* getHorizontalKernelMatrix() {
void createHorizontalKernelMatrix() {
float matrix[9] = {-1, 0, 1,
-1, 0, 1,
-1, 0, 1 };
CvMat* kernel = cvCreateMat(3, 3, CV_32FC1);
return setupKernelMatrixFromArray(kernel, matrix);
horizontalMatrix = cvCreateMat(3, 3, CV_32FC1);
horizontalMatrix = setupKernelMatrixFromArray(horizontalMatrix, matrix);
}
CvMat* getVerticalKernelMatrix() {
void createVerticalKernelMatrix() {
float matrix[9] = {-1,-1,-1,
0, 0, 0,
1, 1, 1 };
CvMat* kernel = cvCreateMat(3, 3, CV_32FC1);
return setupKernelMatrixFromArray(kernel, matrix);
verticalMatrix = cvCreateMat(3, 3, CV_32FC1);
verticalMatrix = setupKernelMatrixFromArray(verticalMatrix, matrix);
}
};

View File

@ -4,19 +4,19 @@
class RobertsOperator : public AbstractOperator {
public:
CvMat* getHorizontalKernelMatrix() {
void createHorizontalKernelMatrix() {
float matrix[9] = {0, 0, 0,
0, 1, 0,
0, 0,-1 };
CvMat* kernel = cvCreateMat(3, 3, CV_32FC1);
return setupKernelMatrixFromArray(kernel, matrix);
horizontalMatrix = cvCreateMat(3, 3, CV_32FC1);
horizontalMatrix = setupKernelMatrixFromArray(horizontalMatrix, matrix);
}
CvMat* getVerticalKernelMatrix() {
void createVerticalKernelMatrix() {
float matrix[9] = {0, 0, 0,
0, 0, 1,
0,-1, 0 };
CvMat* kernel = cvCreateMat(3, 3, CV_32FC1);
return setupKernelMatrixFromArray(kernel, matrix);
verticalMatrix = cvCreateMat(3, 3, CV_32FC1);
verticalMatrix = setupKernelMatrixFromArray(verticalMatrix, matrix);
}
};

View File

@ -4,19 +4,19 @@
class SobelOperator : public AbstractOperator {
public:
CvMat* getHorizontalKernelMatrix() {
void createHorizontalKernelMatrix() {
float matrix[9] = {-1, 0, 1,
-2, 0, 2,
-1, 0, 1 };
CvMat* kernel = cvCreateMat(3, 3, CV_32FC1);
return setupKernelMatrixFromArray(kernel, matrix);
horizontalMatrix = cvCreateMat(3, 3, CV_32FC1);
horizontalMatrix = setupKernelMatrixFromArray(horizontalMatrix, matrix);
}
CvMat* getVerticalKernelMatrix() {
void createVerticalKernelMatrix() {
float matrix[9] = {-1,-2,-1,
0, 0, 0,
1, 2, 1 };
CvMat* kernel = cvCreateMat(3, 3,CV_32FC1);
return setupKernelMatrixFromArray(kernel, matrix);
verticalMatrix = cvCreateMat(3, 3,CV_32FC1);
verticalMatrix = setupKernelMatrixFromArray(verticalMatrix, matrix);
}
};

View File

@ -27,7 +27,6 @@ bool WindowClass::registerClass() {
*/
void WindowClass::setToDefault() {
setStyle( CS_HREDRAW | CS_VREDRAW );
setIconType(IDI_APPLICATION);
setCursorType(IDC_ARROW);
setBackgroundBrushColor(WHITE_BRUSH);
setMenuName(L"MainMenu");

View File

@ -3,7 +3,7 @@
#include <windows.h>
/**
* Класс регистрации WNDCLASS
* Класс регистрации WNDCLASS
* @author aNNiMON
*/
class WindowClass {

Binary file not shown.