Перейти к содержимому
Compvision.ru

Доска почета


Popular Content

Showing most liked content on 30.03.2011 во всех областях

  1. 1 point
    Здесь Кто-нибудь собирается участвовать?
  2. 1 point
    Решил отписаться про свои успехи. в общем на .NET и EmguCV забил - раньше не сталкивался, с ходу не пошло, разбираться некогда. Решил попробовать MFC, хоть с ним тоже раньше не сталкивался, но начал получать хоть какие-то результаты, потому решил на нем остановиться. Для таких начинающих как я расскажу что и как я делал: 1) создал MFC проект в Visual Studio 2010 2) на dialog (главную форму) бросил компонент Picture Control 3) в свойствах Picture Control в поле "Тип" установил "Точечный рисунок", в поле "ИД" стоит IDC_STATIC - его нужно изменить, НЕ выбрать из выпадающего списка, а вбить ручками. я, например, вбил IDC_CAP_STATIC. я еще ставил "Изображение по центру" в true, иначе у меня не получалось растянуть Picture Control по форме... 4) потом нужно добавить переменную для Picture Control, для того чтоб можно было с ним работать. для этого клацаем правой кн. по Picture Control и жмем "Добавить переменную". потом указываем имя, например m_cap, и тип переменной CStatic 5) теперь нужно прикрутить OpenCV к проекту. я делал как сказано тут. там же и простой примерчик. 6) в OpenCV изображения представлены типом IplImage, а компонент Picture Control понимает Bitmap. для преобразования типов я воспользовался кодом, который нашел в сети (спасибо автору ): HBITMAP CreateRGBBitmap(IplImage* _Grab) { char *App; LPBITMAPINFO lpbi = new BITMAPINFO; lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); lpbi->bmiHeader.biWidth = _Grab->width; lpbi->bmiHeader.biHeight =_Grab->height; lpbi->bmiHeader.biPlanes = 1; lpbi->bmiHeader.biBitCount = 24; lpbi->bmiHeader.biCompression = BI_RGB; lpbi->bmiHeader.biSizeImage = WIDTHBYTES((DWORD)_Grab->width * 8) * _Grab->height; lpbi->bmiHeader.biXPelsPerMeter = 0; lpbi->bmiHeader.biYPelsPerMeter = 0; lpbi->bmiHeader.biClrUsed = 0; lpbi->bmiHeader.biClrImportant = 0; void* pBits; HBITMAP hBitmap = CreateDIBSection( NULL,lpbi,DIB_RGB_COLORS,(void **)&pBits,NULL,0 ); delete lpbi; if ( hBitmap ) App=(char*)pBits; long int length=0; if(_Grab->nChannels==1) // Серое или бинарное { length = _Grab->width*(_Grab->height); for (int i=0;i<_Grab->height;i++) { for (int j=0;j<_Grab->width;j++) { App[_Grab->width*3*(_Grab->height-i-1)+j*3]=_Grab->imageData[_Grab->width*(i)+j]; App[_Grab->width*3*(_Grab->height-i-1)+j*3+1]=_Grab->imageData[_Grab->width*(i)+j]; App[_Grab->width*3*(_Grab->height-i-1)+j*3+2]=_Grab->imageData[_Grab->width*(i)+j]; } } } if(_Grab->nChannels==3) // Цветное { for (int i=0;i<_Grab->height;i++) { // Копируем память memcpy(App+_Grab->width*3*(_Grab->height-i-1),_Grab->imageData+_Grab->width*3*i,_Grab->width*3); } } return hBitmap; } 7) теперь, уже имея картинку pBitmap с типом HBITMAP, можно отобразить ее на Picture Control (напомню, у нас есть переменная m_cap). для этого делаем следующее: // Получить контекст устройства CDC* dc = m_cap.GetDC(); // Создать контекст устройства в памяти HDC hMemDC = CreateCompatibleDC(dc->m_hDC); // Поместить растровое изображение в dc памяти и // сохранить старое изображение HGDIOBJ hOldBm = SelectObject(hMemDC, pBitmap); // Копировать содержимое dc памяти в dc экрана BitBlt(dc->m_hDC, 0, 0, width, height, // Приемник: dc экрана hMemDC, 0, 0, SRCCOPY); // Источник: dc памяти // Восстановить старое растровое изображение в dc памяти SelectObject(hMemDC, hOldBm); // Уничтожить dc памяти DeleteDC(hMemDC); // Освободить полученый контекст устройства ReleaseDC(dc); // Уничтожить растровое изображение DeleteObject(pBitmap); все... картинку показываем!!! отображать видео у меня сначала не получилось, точнее картинка сильно мерцала. выделял отображение в отдельный поток - не помогло. потом, в сети, я вычитал что в MFC и Windows все основывается на сообщениях (можно почитать тут) и для вывода видео можно использовать таймер. делается это так: 1) создаем таймер, захватчик камеры, и указатель на картинку: UINT_PTR m_nTimer; CvCapture* capture; IplImage* frame; а в методе OnInitDialog() дописываем: // Инициализация таймера // Таймер будет посылать WM_TIMER сообщение основному // рамочному окну каждые 30 миллисекунд m_nTimer = SetTimer(1, 30, 0); // получаем любую подключенную камеру capture = cvCreateCameraCapture(CV_CAP_ANY); assert( capture ); 2) добавляем обработку сообщений от таймера. т.е. жмем Проект->Мастер классов, выбираем имя класса диалога (как правило заканчивается на ...Dlg), переходим на вкладку "Сообщения" и в левой части находим WM_TIMER и добавляем обработчик (в правой части появится OnTimer и т.д.). 3) в обработчике OnTimer() дописываем захват изображения с камеры и отображение в Picture Control: frame = cvQueryFrame( capture ); DrawData(CreateRGBBitmap(frame)); void CtestDlg::DrawData(HBITMAP pBitmap) { // Получить контекст устройства CDC* dc = m_cap.GetDC(); // Создать контекст устройства в памяти HDC hMemDC = CreateCompatibleDC(dc->m_hDC); // Поместить растровое изображение в dc памяти и // сохранить старое изображение HGDIOBJ hOldBm = SelectObject(hMemDC, pBitmap); // Копировать содержимое dc памяти в dc экрана BitBlt(dc->m_hDC, 0, 0, width, height, // Приемник: dc экрана hMemDC, 0, 0, SRCCOPY); // Источник: dc памяти // Восстановить старое растровое изображение в dc памяти SelectObject(hMemDC, hOldBm); // Уничтожить dc памяти DeleteDC(hMemDC); // Освободить полученый контекст устройства ReleaseDC(dc); // Уничтожить растровое изображение DeleteObject(pBitmap); UpdateData(FALSE); } 4) ну и нужно при выходе из программы освободить ресурсы: cvReleaseCapture( &capture ); cvReleaseImage(&frame); KillTimer(1); я это делаю в обработчике сообщения WM_CLOSE... ну, вроде и все... надеюсь ничего не пропустил и кому-то это поможет
×