【发布时间】:2021-01-22 17:11:46
【问题描述】:
我在C++ 中使用OpenCV 在屏幕截图和磁盘中的图像之间执行模板匹配。我的屏幕截图似乎类型为CV_8UC4,但我的模板图像类型为CV_8UC3。这会导致matchTemplate 函数得到一个断言错误:
OpenCV(4.3.0) C:\...\opencv4\src\4.3.0-0c6047baf6.clean\modules\imgproc\src\templmatch.cpp:1104: error: (-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 in function 'cv::matchTemplate'
为了解决这个问题,我尝试使用 convertTo 函数将两个 cv::Mats 转换为相同的类型:
screen_shot.convertTo(screen_shot, CV_8UC3);
template_image.convertTo(template_image, CV_8UC3);
令人惊讶的是,这“没有”。两个cv::Mats 的类型在调用后都不会被修改。为什么?
另一个尝试是修改屏幕截图创建代码以直接生成类型CV_8UC3。但是,这会使GetDIBits() 函数失败:
bool dump_window_screen_to_opencv_mat(const HWND window_handle, cv::Mat& output_mat)
{
auto* const h_window_dc = GetDC(window_handle);
auto* const h_window_compatible_dc = CreateCompatibleDC(h_window_dc);
if (!h_window_compatible_dc)
{
return false;
}
if (!SetStretchBltMode(h_window_compatible_dc, COLORONCOLOR))
{
DeleteDC(h_window_compatible_dc);
return false;
}
const auto window_resolution = // ...
const auto loc_window_width = window_resolution.x;
const auto loc_window_height = window_resolution.y;
const auto h_bit_map = CreateCompatibleBitmap(h_window_dc, loc_window_width, loc_window_height);
if (!h_bit_map)
{
DeleteDC(h_window_compatible_dc);
return false;
}
BITMAPINFOHEADER bit_map_info_header;
bit_map_info_header.biSize = sizeof(BITMAPINFOHEADER);
bit_map_info_header.biWidth = loc_window_width;
bit_map_info_header.biHeight = -loc_window_height;
bit_map_info_header.biPlanes = 1;
bit_map_info_header.biBitCount = 32;
bit_map_info_header.biCompression = BI_RGB;
bit_map_info_header.biSizeImage = 0;
bit_map_info_header.biXPelsPerMeter = 0;
bit_map_info_header.biYPelsPerMeter = 0;
bit_map_info_header.biClrUsed = 0;
bit_map_info_header.biClrImportant = 0;
if (!SelectObject(h_window_compatible_dc, h_bit_map))
{
DeleteObject(h_bit_map);
DeleteDC(h_window_compatible_dc);
return false;
}
if (!StretchBlt(
h_window_compatible_dc,
0, 0,
loc_window_width, loc_window_height,
h_window_dc,
0, 0,
loc_window_width, loc_window_height,
SRCCOPY))
{
DeleteObject(h_bit_map);
DeleteDC(h_window_compatible_dc);
return false;
}
output_mat.create(loc_window_height, loc_window_width, CV_8UC4); // <-- Here we can specify the image type
const auto has_di_bits_succeeded = GetDIBits(
h_window_dc,
h_bit_map,
0,
loc_window_height,
output_mat.data,
reinterpret_cast<BITMAPINFO*>(&bit_map_info_header),
DIB_RGB_COLORS);
if (!has_di_bits_succeeded)
{
DeleteObject(h_bit_map);
DeleteDC(h_window_compatible_dc);
return false;
}
DeleteObject(h_bit_map);
DeleteDC(h_window_compatible_dc);
return true;
}
知道如何修复此代码以生成正确的图像类型,或者我可以尝试完全不同的方法吗?
在opencv.org查看这个相关问题:
https://answers.opencv.org/question/236225
【问题讨论】:
标签: c++ windows opencv winapi visual-c++