Mat
,然后使用模板匹配从使用Java.Robot
拍摄的屏幕截图中找到它们的位置。当进行模板匹配时,会抛出以下错误。
OpenCV Error: Assertion failed ((depth == CV_8U || depth == CV_32F)
&& type == _templ.type() && _img.dims() <= 2) in cv::matchTemplate
在搜索后,看起来问题是我正在尝试使用的两个Mat
没有相同的“类型”。我不确定这是什么意思。我猜这是Mat
的CvType
,如果我打印出图像和模板的CvType
,我得到一个4 == CvType.CV_32SC1
的type()
作为我的模板,我得到一个20 == CvType.CV_32SC3
的type()
。
但我觉得这不是我要比较的正确type()
,我有一种感觉它指的是数据存储在Mat
中的数据类型?但我没有好的链接来支持这个想法,只是从许多SO搜索中记住的。
这是我加载jpg图像到Mat
中的代码:
Mat pic_ = Imgcodecs.imread("MyPath\\image.jpg");
pic_.convertTo(pic_, CvType.CV_32SC1);
这里第二行将我的type()
从20更改为16,尽管根据我上次的评论,我不认为这是将Mat
更改以匹配图像的正确方法?因为将此Mat
进行convertTo
以匹配屏幕截图的类型(如下)无法修复错误?
以下是我创建图像Mat
的方式。
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage screenShot = rob.createScreenCapture(screenRect);
Mat screenImage = bufferedImageToMat(screenShot);
我首先使用 Java.Robot.createScreenCapture
拍摄屏幕截图,然后使用 Mat
进行转换。
private Mat bufferedImageToMat(BufferedImage inBuffImg)
{
BufferedImage image = new BufferedImage(inBuffImg.getWidth(), inBuffImg.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d= image.createGraphics();
g2d.drawImage(inBuffImg, 0, 0, null);
g2d.dispose();
Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_32SC1);
int[] data = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
mat.put(0, 0, data);
return mat;
}
从我所了解的情况来看,由Robot
创建的BufferedImage
类型为BufferedImage.TYPE_3BYTE_BGR
,这导致我在尝试获取像素数据时出现错误“DataBufferInt不能转换为DataBufferByte”。因此,根据链接的问题,我将BufferedImage
重绘为类型BufferedImage.TYPE_INT_RGB
,并将数据作为DataBufferInt
提取。
所以说,总的来说,我应该尝试匹配Mat.type()
还是我的问题在其他地方?如果不是在其他地方,如何修改其中一个Mat
,使其可以与Imgproc.matchTemplate
正确使用?
我觉得最简单的解决方案是将从文件加载的图像转换为与屏幕截图的Mat
相匹配吗?
编辑: 导致错误的精确代码部分如下
// Mat imageTemplate is a function argument; the loaded jpg image
// Take a picture of the screen
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage screenShot = rob.createScreenCapture(screenRect);
Mat screenImage = bufferedImageToMat(screenShot);
// Create the result matrix
int result_cols = screenImage.cols() - imageTemplate.cols() + 1;
int result_rows = screenImage.rows() - imageTemplate.rows() + 1;
Mat result = new Mat(result_rows, result_cols, CvType.CV_32SC1);
newStatus("ScreenType: " + screenImage.type());
newStatus("TemplaType: " + imageTemplate.type());
// Choose a matching method
int matchMethod = Imgproc.TM_SQDIFF_NORMED;
// Do the Matching and Normalize
Imgproc.matchTemplate(screenImage, imageTemplate, result, matchMethod);
// Error occurs on previous line
cvtColor(... , COLOR_BGR2GRAY)
。 - MikibufferedImageToMat
中,如果我使用CvType.CV_32FC3
并且在转换读取的模板时使用相同的类型,它就“可以工作”。尽管从屏幕图像中读取的数据没有写入函数中的Mat
,因为我遇到了“Mat数据类型不兼容:21”的错误,当我第一次使用该函数时(尽管它是16)。//我想我不确定从这里问什么,除了初学者的问题“出了什么问题”..? - KDecker