opencv (Java) — сопоставление с неизвестным исключением

#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 мс в течение определенного периода, а затем завершаю работу приложения, это нормально. Это определенно не лучший подход для каждого варианта использования, поэтому будьте осторожны с слепой копипастой 😀