powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Получить screenshot windows в cv::Mat
3 сообщений из 3, страница 1 из 1
Получить screenshot windows в cv::Mat
    #38235079
rs4i
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Собственно, название темы. Как?
К сожалению, я не силен в графике и с соответствующими библиотеками знаком слабо.
Думал использовать 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
Получить screenshot windows в cv::Mat
    #38236274
rs4i
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пришлось копировать через 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
Получить screenshot windows в cv::Mat
    #38241638
rs4i
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Выкинул один буфер.
Лучше сделать нельзя.
С темы ухожу.
Спасибо за внимание.

Код: 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
3 сообщений из 3, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Получить screenshot windows в cv::Mat
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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