Android4OpenCV: настройка разрешения при запуске

Я использую Android4OpenCV для некоторой обработки живого изображения, и я хотел бы использовать наименьшее разрешение, которое может предложить камера. Разрешение по умолчанию - самое большое, которое может предложить камера.

Я смотрю на 3-й пример, который позволяет пользователю изменять разрешение с помощью меню. Я хотел бы изменить этот пример, чтобы изменить разрешение при запуске, а не требовать, чтобы пользователь прошел через меню. Чтобы сделать это, я просто добавляю две строки в пустой onCameraViewStarted() функция:

public void onCameraViewStarted(int width, int height) {
    android.hardware.Camera.Size res = mOpenCvCameraView.getResolutionList().get(mOpenCvCameraView.getResolutionList().size()-1);
    mOpenCvCameraView.setResolution(res);
}

И дело в том, что это прекрасно работает на моем Galaxy Nexus под управлением Android 4.2.2. Приложение запускается, и разрешение устанавливается правильно.

Однако, когда я запускаю точно такое же приложение на планшете Nexus 7 под управлением Android 5.1, приложение зависает при вызове setResolution(), На самом деле он работает нормально один раз, но затем зависает во второй раз, когда вы пытаетесь запустить его, даже если вы полностью выходите из приложения, удаляете его из запущенных приложений или перезагружаете устройство. Другие пользователи также сообщают об этой же ошибке, так что это не просто устройство Nexus 7 - фактически, моя Galaxy Nexus, кажется, единственное устройство, где это работает.

В частности, приложение переходит в setResolution() функция, которая затем вызывает org.opencv.android.JavaCameraView.disconnectCamera(), который выглядит так:

(Примечание: этот код является внутренним для библиотеки OpenCV4Android, это не мой код)

protected void disconnectCamera() {
    /* 1. We need to stop thread which updating the frames
     * 2. Stop camera and release it
     */
    Log.d(TAG, "Disconnecting from camera");
    try {
        mStopThread = true;
        Log.d(TAG, "Notify thread");
        synchronized (this) {
            this.notify();
        }
        Log.d(TAG, "Wating for thread");
        if (mThread != null)
            mThread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        mThread =  null;
    }

    /* Now release camera */
    releaseCamera();
}

Глядя на логи, я вижу, что поток застревает на synchronized(this) линия. Единственное, что синхронизируется на этом объекте, это внутренний JavaCameraView.CameraWorker класс, который является mThread переменная в приведенном выше коде, запускаемая классом JavaCameraView:

(Примечание: этот код является внутренним для библиотеки OpenCV4Android, это не мой код)

private class CameraWorker implements Runnable {

    public void run() {
        do {
            synchronized (JavaCameraView.this) {
                try {
                    JavaCameraView.this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            if (!mStopThread) {
                if (!mFrameChain[mChainIdx].empty())
                    deliverAndDrawFrame(mCameraFrame[mChainIdx]);
                mChainIdx = 1 - mChainIdx;
            }
        } while (!mStopThread);
        Log.d(TAG, "Finish processing thread");
    }
}

Я попытался использовать этот код, изменив notify() на notifyAll(), и поддерживая список потоков CameraWorker и присоединяясь к каждому из них. Но несмотря ни на что, приложение все еще висит на disconnectCamera() вызов.

Мои вопросы:

  • Как я могу изменить третий пример OpenCV4Android, чтобы его разрешение устанавливалось при запуске?

  • Что вызывает зависание приложения?

  • Почему это работает на некоторых устройствах, но не на других?

Редактировать: я не получил ни одного комментария или ответа, поэтому я разместил здесь ссылки на форумы OpenCV.

Редактировать 2: Согласно совету Сириэля, я попытался установить разрешение после того, как прошло несколько кадров:

int frames = 0;
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

    frames++;

    if(frames == 6){
        android.hardware.Camera.Size res = mOpenCvCameraView.getResolutionList().get(mOpenCvCameraView.getResolutionList().size()-1);
        mOpenCvCameraView.setResolution(res);

    }

    return inputFrame.rgba();
}

Тем не менее, теперь это застревает в одном и том же месте, даже на моем Galaxy Nexus, который работает, если я установлю разрешение в onCameraViewStarted() функция. Я пытался увеличить количество кадров до 7 и даже до 100, но я всегда застреваю в одном и том же месте.

1 ответ

Самый важный вопрос в вашей ситуации: работает ли он, если вы вообще не изменяете код - можете ли вы изменить разрешение (через меню) без сбоя приложения?
Если да, то ответ, скорее всего, прост - это та же ошибка в OpenCV, что и в версии Windows: перед изменением разрешения камеры или fps (и, скорее всего, любого свойства) вам нужно захватить хотя бы одну (для уверенности используйте 3-5) кадр до изменения этого свойства.
Если нет, скорее всего, вы ничего не можете сделать самостоятельно - заполните отчет об ошибке и дождитесь комментариев. Единственная альтернатива - использовать другую библиотеку для захвата кадров с камеры и преобразования ее в объект OpenCV.

Другие вопросы по тегам