Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Получить screenshot windows в cv::Mat / 3 сообщений из 3, страница 1 из 1
22.04.2013, 14:32
    #38235079
rs4i
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получить screenshot windows в cv::Mat
Собственно, название темы. Как?
К сожалению, я не силен в графике и с соответствующими библиотеками знаком слабо.
Думал использовать OpenGL, нашел красивый код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
//glReadBuffer( GL_FRONT );
cv::Mat img( 200, 200, CV_8UC3 );
glPixelStorei( GL_PACK_ALIGNMENT, ( img.step & 3 )? 1: 4 );
glPixelStorei( GL_PACK_ROW_LENGTH, img.step/img.elemSize() );
glReadPixels( 0, 0, img.cols, img.rows, GL_BGR_EXT, GL_UNSIGNED_BYTE, img.data );
//cv::Mat flipped( img );
//cv::flip( img, flipped, 0 );
//cv::imwrite( "C:\\Projects\\OpenCV\\snapshot.png", img );


Выдает чёрный квадрат.
Заставить работать не удалось.

Пробовал Win32api, наворочал костылей, получил тормоза.
Вот кривой и тормозной, но рабочий код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
std::auto_ptr< cv::Mat > getScreen(){
	HWND hDW = GetDesktopWindow();	
	HDC hDWDC = GetWindowDC( hDW );
	RECT rect; GetWindowRect( hDW, &rect );
	unsigned width = rect.right;
	unsigned height = rect.bottom;
	HDC hScreen = CreateCompatibleDC( hDWDC );
	HBITMAP hBM = CreateCompatibleBitmap( hDWDC, width, height );
	HGDIOBJ temp = SelectObject( hScreen, hBM );
	BitBlt( hScreen, 0, 0, width, height, hDWDC, 0, 0, SRCCOPY );

	std::auto_ptr< cv::Mat > screen( new cv::Mat( height, width, CV_8UC3 ) );

	for( unsigned y = 0; y < height; ++y )
        for( unsigned x = 0; x < width; ++x ){
			COLORREF color = GetPixel( hScreen, x, y );
			screen->data[ ( y * screen->cols + x ) * screen->elemSize() + 0 ] = GetBValue( color ); // B
			screen->data[ ( y * screen->cols + x ) * screen->elemSize() + 1 ] = GetGValue( color ); // G
			screen->data[ ( y * screen->cols + x ) * screen->elemSize() + 2 ] = GetRValue( color ); // R
		}

	// нужно поудалять созданные объекты!!!

	return screen;
}



Пробовал задействовать GetDIBits, картинка скосилась.
Видимо в Bitmap строки выровнены по границе слова (кратны 4).
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
BITMAPINFO BMI; ZeroMemory( &BMI, sizeof BMI );
BMI.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
BMI.bmiHeader.biWidth = width;
BMI.bmiHeader.biHeight = -height;
BMI.bmiHeader.biPlanes = 1;
BMI.bmiHeader.biBitCount = 24;
BMI.bmiHeader.biCompression = BI_RGB;
	
int result = GetDIBits( hScreen, hBM, 0, height, screen->data, &BMI, DIB_RGB_COLORS );



Подскажите пожалуйста
1. Как заставить работать glReadPixels (или другую функцию OpenGL) с экраном Windows.
2. Как заставить GDI BitBlt или GetDIBits копировать данные в cv::Mat с учетом выравнивания строк.
...
Рейтинг: 0 / 0
23.04.2013, 11:42
    #38236274
rs4i
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получить screenshot windows в cv::Mat
Пришлось копировать через 2 промежуточных буфера.
И хотя, скорость работы меня уже устраивает,
хотелось бы знать, нет ли более простого способа?

Итого:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
std::auto_ptr< cv::Mat > getScreen(){
	// Получить параметры экрана
	HWND hDW = GetDesktopWindow();	
	HDC hDWDC = GetWindowDC( hDW );
	int width = GetSystemMetrics( SM_CXSCREEN );
	int height = GetSystemMetrics( SM_CYSCREEN );

	// Скопировать экран в буфер Windows
	HDC hScreen = CreateCompatibleDC( hDWDC ); // - DeleteDC( hScreen );
	HBITMAP hBM = CreateCompatibleBitmap( hDWDC, width, height ); // - DeleteObject( hBM );
	HGDIOBJ temp = SelectObject( hScreen, hBM ); // - SelectObject( hScreen, temp );
	BitBlt( hScreen, 0, 0, width, height, hDWDC, 0, 0, SRCCOPY );

	// Скопировать в свой буфер
	const int colorSize = 3;
	const int alignment = 4;
	int step = ( width * colorSize / alignment + ( width * colorSize % alignment? 1: 0 ) ) * alignment;
	char* buffer = new char[ step * height ]; // - delete[] buffer;
	BITMAPINFO BMI; // ZeroMemory( &BMI, sizeof BMI );
	BMI.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
	BMI.bmiHeader.biWidth = width;
	BMI.bmiHeader.biHeight = -height;
	BMI.bmiHeader.biPlanes = 1;
	BMI.bmiHeader.biBitCount = 24;
	BMI.bmiHeader.biCompression = BI_RGB;	
	GetDIBits( hScreen, hBM, 0, height, buffer, &BMI, DIB_RGB_COLORS );	

	// Заполнить cv::Mat из буфера
	std::auto_ptr< cv::Mat > screen( new cv::Mat( height, width, CV_8UC3 ) );
	for( int y = 0; y < height; ++y )
        for( int x = 0; x < width; ++x ){
			int pScreen = ( y * screen->cols + x ) * screen->elemSize();
			int pBuffer = y * step + x * colorSize;
			screen->data[ pScreen + 0 ] = buffer[ pBuffer + 0 ]; // B
			screen->data[ pScreen + 1 ] = buffer[ pBuffer + 1 ]; // G
			screen->data[ pScreen + 2 ] = buffer[ pBuffer + 2 ]; // R
		}

	// Удалить не нужные объекты
	SelectObject( hScreen, temp );
	DeleteObject( hBM );
	DeleteDC( hScreen );
	delete[] buffer;

	return screen;
}
...
Рейтинг: 0 / 0
26.04.2013, 14:59
    #38241638
rs4i
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получить screenshot windows в cv::Mat
Выкинул один буфер.
Лучше сделать нельзя.
С темы ухожу.
Спасибо за внимание.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
#include< windows.h >
#include< opencv2/opencv.hpp >

class Screen{
public:
	Screen(){
		// Параметры экрана
		HWND hwnd = GetDesktopWindow();	
		hWDC = GetWindowDC( hwnd );
		width = GetSystemMetrics( SM_CXSCREEN );
		height = GetSystemMetrics( SM_CYSCREEN );

		// Совместимый контекст в памяти
		hScreen = CreateCompatibleDC( hWDC ); // - DeleteDC( hScreen );
		hBM = CreateCompatibleBitmap( hWDC, width, height ); // - DeleteObject( hBM );
		hBM_Temp = SelectObject( hScreen, hBM ); // - SelectObject( hScreen, hBM_Temp );

		// Описание рабочего массива бит совместимого контекста в памяти
		BMI.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
		BMI.bmiHeader.biWidth = width;
		BMI.bmiHeader.biHeight = -height;
		BMI.bmiHeader.biPlanes = 1;
		BMI.bmiHeader.biBitCount = 24;
		BMI.bmiHeader.biCompression = BI_RGB;

		// Массив данных скриншота
		const int colorSize = 3; // Размер пикселя
		const int alignment = 4; // Выравнивание строки		 
		int step = ( int )ceil( width * colorSize / ( double )alignment ) * alignment; // Шаг строки
		//int step = ( width * colorSize / alignment + ( width * colorSize % alignment? 1: 0 ) ) * alignment; // Шаг строки
		data = new char[ step * height ]; // - delete[] data;

		// Скриншот
		screen = new cv::Mat( height, width, CV_8UC3, data, step ); // - delete screen;
	};

	~Screen(){
		SelectObject( hScreen, hBM_Temp );
		DeleteObject( hBM );
		DeleteDC( hScreen );
		delete screen; screen = NULL;
		delete[] data; data = NULL;
	};

	cv::Mat& get(){
		BitBlt( hScreen, 0, 0, width, height, hWDC, 0, 0, SRCCOPY );
		GetDIBits( hScreen, hBM, 0, height, data, &BMI, DIB_RGB_COLORS );
		return *screen;
	};

private:
	HDC hWDC; // Контекст экрана
	HDC hScreen; // Совместимый с экраном контекст в памяти
	HBITMAP hBM; // Рабочий массив бит совместимого контекста в памяти
	BITMAPINFO BMI; // Описание рабочего массива бит совместимого контекста в памяти

	int width; // Ширина экрана в пикселях
	int height; // Высота экрана в пикселях

	char* data; // Массив данных скриншота
	cv::Mat* screen; // Скриншот

	HGDIOBJ hBM_Temp; // Массив бит совместимого контекста в памяти созданный по умолчанию	
};

int main(){
	Screen sh;
	cv::Mat screen = sh.get();
	cv::imwrite( "C:\\MyPath\\snapshot.png", screen );
	return 0;
}
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Получить screenshot windows в cv::Mat / 3 сообщений из 3, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]