使用OpenCV进行模板匹配的图像类型存在问题



我在C++中使用OpenCV来执行屏幕截图和磁盘图像之间的模板匹配。我的屏幕截图的类型似乎是CV_8UC4,但我的模板图像的类型是CV_8UC3。这导致matchTemplate函数获得断言错误:

OpenCV(4.3.0) C:...opencv4src4.3.0-0c6047baf6.cleanmodulesimgprocsrctemplmatch.cpp:1104: error: (-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 in function 'cv::matchTemplate'

为了解决这个问题,我尝试使用convertTo函数将两个cv::Mat转换为相同的类型:

screen_shot.convertTo(screen_shot, CV_8UC3);
template_image.convertTo(template_image, CV_8UC3);

令人惊讶的是;什么都没有";。两个cv::Mat的类型在调用后都没有更改。为什么?

另一个尝试是修改屏幕截图创建代码以直接生成类型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

在cv::Mat::convertTortype(第二个参数(描述中的规范中,说明它是

所需的输出矩阵类型,或者更确切地说,深度,因为通道的数量与输入的数量相同;如果rtype为负数,则输出矩阵将具有与输入相同的类型。

我不确定这是否是问题所在,但找不到任何其他解释。

尝试使用带有适当颜色代码的cv::cvtColor,在您的情况下是cv::COLOR_xxxA2xxx中的一个,很可能是cv::COLOR_BGRA2BGR(或cv::COLOR_RGBA2RGB,这无关紧要,因为它们是相等的,并且只有alpha通道被删除(。或者反过来,如果您想将alpha通道添加到另一个图像中,这最适合您。我主要使用它来将图像更改为灰度级,如下所示:

cv::Mat img_gray, image = imread(argv[1], cv::IMREAD_UNCHANGED);
cv::cvtColor(image, img_gray, cv::COLOR_BGR2GRAY);

最新更新