#java #opencv
Вопрос:
Пытаюсь использовать метод org.opencv.imgproc
matchTemplate, но получаю java.lang.Exception: unknown exception
отказ без каких-либо других подробностей.
Я называю это следующим образом:
private Mat matchTemplate(final Mat source) {
final Mat sample = loadTemplate();
final Mat result = new Mat();
Imgproc.matchTemplate(source, sample, result, Imgproc.TM_CCOEFF_NORMED);
Imgproc.threshold(result, result, 0.1, 1, Imgproc.THRESH_TOZERO);
return resu<
}
Где значения, входящие в шаблон, являются:
- Источник:
Mat [ 1440*2560*CV_8UC3, isCont=true, isSubmat=false
- образец:
Mat [ 22*46*CV_8UC3, isCont=true, isSubmat=false
- Результат:
Mat [ -1*-1*CV_8UC1, isCont=false, isSubmat=false
Сначала я подумал, что это несоответствие между источником и образцом, но, глядя на то, что происходит, кажется, все в порядке?
Что еще я могу попробовать или как я могу получить дополнительную информацию из ошибки для дальнейшей отладки?
правка: Поэтому я просто попытался нормализовать свои входные данные, чтобы посмотреть, поможет ли это, и заметил, что он тоже выходит из строя на том же входе. Теперь я думаю, что просто неправильно строю исходное изображение.
Я делаю снимок экрана с помощью:
public class ScreenshotServiceImpl implements ScreenshotService {
private final FFmpegFrameGrabber grabber;
private final ToOrgOpenCvCoreMat toCore = new ToOrgOpenCvCoreMat();
@Override
@SneakyThrows
public Mat take() {
grabber.start();
final Mat output = toCore.convert(grabber.grab());
grabber.stop();
return output;
}
}
Возможно ли, что преобразователь делает что-то странное с изображением?
Ответ №1:
Так что, оказывается, раннее закрытие граббера, как я и делал, было причиной проблемы. Я наивно предположил, что при использовании функции преобразования я делал копию значения и больше не требовал, чтобы оно было открыто.
Чтобы решить эту проблему, сохранив структуру моего приложения, я обновил take()
метод:
@Override
@SneakyThrows
public Mat take() {
if (!grabber.isCloseInputStream()) {
grabber.stop();
}
grabber.start();
return toCore.convert(grabber.grabImage());
}
Это оставит рамку захвата открытой для дальнейшей обработки, но закроет ее при съемке другого снимка экрана.
Для моего случая использования, когда я делаю снимок экрана каждые 50 мс в течение определенного периода, а затем завершаю работу приложения, это нормально. Это определенно не лучший подход для каждого варианта использования, поэтому будьте осторожны с слепой копипастой 😀