Хобрук: Ваш путь к мастерству в программировании

Android, OpenCv, размеры захваченных фотографий не соответствуют предварительному просмотру

У меня есть подкласс JavaCameraView, который позволяет пользователю делать и сохранять фотографии. Проблема в том, что кадр предварительного просмотра, который я получаю через onCameraFrame(), не имеет тех же размеров, что и фотография, которая захвачена и сохранена, в результате чего сохраненное изображение выглядит обрезанным относительно кадра. Входной кадр 1080 * 1440 (3:4), а захват 2988 * 5312 (9:16).

Мой код выглядит следующим образом:

public void takePicture() {
    Log.i(CaptureActivity.TAG, "MyCameraView, takePicture()");
    // Postview and jpeg are sent in the same buffers if the queue is not empty when performing a capture.
    // Clear up buffers to avoid mCamera.takePicture to be stuck because of a memory issue
    mCamera.setPreviewCallback(null);

    // PictureTakenListener is implemented by the current class
    mCamera.takePicture(null, null, this);
}

@Override
public void onPictureTaken(byte[] bytes, Camera camera) {
    // The camera preview was automatically stopped. Start it again.
    mCamera.startPreview();
    mCamera.setPreviewCallback(this);

    Mat mat = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.CV_LOAD_IMAGE_UNCHANGED);
    Log.d(CaptureActivity.TAG, mat.toString());

    //an interface method to be implemented by CaptureActivity
    if (mPictureTakenListener != null)
        mPictureTakenListener.receivePicture(mat);
}

В другом классе я получаю картинку и сохраняю ее...

@Override
public void receivePicture(Mat mat) {
    File path = new File(Environment.getExternalStorageDirectory() + "/myCamera/");
    path.mkdirs();
    File file = new File(path, System.currentTimeMillis() + "recieved" + ".png");
    String filename = file.toString();
    Log.d(CaptureActivity.TAG, "was imwrite a success? "
        + Imgcodecs.imwrite(filename, mat));    
}

Этот класс также реализует CameraBridgeViewBase.CvCameraViewListener2...

public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
        Log.d(TAG, "frame info " + frame.toString());
        return frame;
    }

Ответы:


1

Ты прав. Не рекомендуется использовать одинаковое соотношение сторон для предварительного просмотра и захвата. Итак, в вашем подклассе вы должны переопределить метод initializeCamera() следующим образом:

@Override
protected void AllocateCache() {
    super.AllocateCache();
    setPictureSize();
}

protected boolean setPictureSize() {
    try {
        Camera.Parameters params = mCamera.getParameters();
        Log.d(TAG, "getSupportedPictureSizes()");
        List<Camera.Size> sizes = params.getSupportedPictureSizes();
        if (sizes == null) {
            Log.w(TAG, "getSupportedPictureSizes() = null, cannot set a custom size");
            return false;
        }

        int maxSize = 0;
        // choose the largest size that matches the preview AR
        for (android.hardware.Camera.Size size : sizes) {
            if (size.height * mFrameWidth != size.width * mFrameHeight) {
                continue; // the picture size doesn't match
            }
            if (maxSize > size.width * size.height) {
                continue; // don't need this size
            }
            params.setPictureSize(size.width, size.height);
            maxSize = size.width * size.height;
        }
        if (maxSize == 0) {
            Log.w(TAG, "getSupportedPictureSizes() has no matches for " + mFrameWidth + 'x' + mFrameHeight);
            return false;
        }
        Log.d(TAG, "try Picture size " + params.getPictureSize().width + 'x' + params.getPictureSize().height);
        mCamera.setParameters(params);
    } catch (Exception e) {
        Log.e(TAG, "setPictureSize for " + mFrameWidth + 'x' + mFrameHeight, e);
        return false;
    }
    return true;
}

}

Как видите, я на самом деле переопределяю метод AllocateCache(), потому что OpenCV не обеспечивает лучшей связи между открытием устройства камеры и запуском предварительного просмотра. Изменение параметров камеры (даже размера изображения) во время предварительного просмотра может привести к сбою на некоторых устройствах.

Обратите внимание, что приведенный выше код даже не пытается установить размер изображения, который не соответствует точно выбранному предварительному просмотру. В 99,9% случаев это нормально, но если странная камера не имеет соответствующего размера изображения для размера предварительного просмотра, который OpenCV выбрал для вашего макета, у вас есть два варианта: либо искать другой размер предварительного просмотра, либо попробовать другой размер изображения, который "достаточно близко".

17.12.2017

2

Вы должны использовать setPreviewSize и setPictureSize по порядку. чтобы настроить то, что вы получаете от предварительного просмотра и takePicture. Обратите внимание, что вы не обязательно найдете одинаковые размеры для обоих из них (обычно доступные размеры takePicture могут быть больше, чем размеры предварительного просмотра), поэтому загляните в getSupportedPreviewSizes и getSupportedPictureSizes, чтобы найти размеры, наиболее подходящие для вашей задачи.

17.12.2017
Новые материалы

Учебные заметки JavaScript Object Oriented Labs
Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

Разбор строк запроса в vue.js
Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
«Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..

Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

Как настроить Selenium в проекте Angular
Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

Аргументы прогрессивного улучшения почти всегда упускают суть
В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

Введение в Джанго Фреймворк
Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..