No puedo acceder a la cámara iMac desde un programa OpenCV de línea de comandos. (Estoy compilando y ejecutando el programa bajo CodeRunner, no Xcode). He leído que Mojave requiere NSCameraUsageDescription en Info.plist y creo que lo estoy incrustando correctamente en el binario. Agregué -sectcreate __TEXT __info_plist Info.plist (que aprendí aquí ) a los indicadores de compilación y cuando ejecuto otool -X -s __TEXT __info_plist videotest | xxd -r (desde la misma publicación de blog) genera:

-?<?xml ve.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSCameraUsageDescription</key>
    <string>Uses camera to see vision targets</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>This app requires to access your microphone in order to access the camera</string>
</dict>
</plist>

(Agregué NSMicrophoneUsageDescription en caso de que intentara abrir el micrófono junto con la cámara).

Este es el resultado cuando ejecuto el programa:

OpenCV version 4.1.0-dev
[ INFO:0] global /Users/steve/Documents/GitHub/ssteve-opencv/modules/videoio/src/videoio_registry.cpp (185) VideoBackendRegistry VIDEOIO: Enabled backends(5, sorted by priority): FFMPEG(1000); GSTREAMER(990); AVFOUNDATION(980); CV_IMAGES(970); CV_MJPEG(960)
[ INFO:0] global /Users/steve/Documents/GitHub/ssteve-opencv/modules/videoio/src/backend_plugin.cpp (248) getPluginCandidates VideoIO pluigin (GSTREAMER): glob is 'libopencv_videoio_gstreamer*.dylib', 1 location(s)
[ INFO:0] global /Users/steve/Documents/GitHub/ssteve-opencv/modules/videoio/src/backend_plugin.cpp (256) getPluginCandidates     - /usr/local/lib: 0
[ INFO:0] global /Users/steve/Documents/GitHub/ssteve-opencv/modules/videoio/src/backend_plugin.cpp (259) getPluginCandidates Found 0 plugin(s) for GSTREAMER
OpenCV: not authorized to capture video (status 0), requesting...
OpenCV: camera failed to properly initialize!
Unable to open camera

Implica que está solicitando acceso, pero nunca recibo un cuadro de diálogo y ninguna aplicación aparece en Preferencias del sistema> Seguridad y privacidad> Cámara.

Aquí está el programa que estoy ejecutando:

#include <iostream>

#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"

using namespace std;
using namespace cv;

int main(int argc, char *argv[]) {
    cout << "OpenCV version " << CV_VERSION << endl;
    VideoCapture cap;
    cap.open(0);
    if (!cap.isOpened()) {
        cerr << "Unable to open camera\n";
        return -1;
    }

    Mat frame;
    for (;;) {
        cap >> frame;
        if (frame.empty()) {
            cerr << "Got blank frame\n";
            return -1;
        }
        imshow("Live", frame);
        if (waitKey(5) >= 0)
        break;
    }

    return 0;
}

Esta es la invocación del compilador:

xcrun clang++ -x c++ -lc++ -o "$out" -std=c++11 -I/usr/local/include/opencv4 -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_imgcodecs -lopencv_videoio -lopencv_calib3d -lopencv_aruco -lopencv_xfeatures2d -lopencv_features2d -sectcreate __TEXT __info_plist Info.plist "${files[@]}" "${@:1}"

¿Qué pieza del rompecabezas me estoy perdiendo?

(Sé que esto es similar a No se puede acceder a la cámara con opencv en Mac Mojave pero esa pregunta nunca fue más allá de un archivo plist mal formado).


En respuesta a la sugerencia de asegurarse de que ffmpeg vea el dispositivo:

$ ffmpeg -hide_banner -f avfoundation -list_devices true -i ""
[AVFoundation input device @ 0x7fed77d16dc0] AVFoundation video devices:
[AVFoundation input device @ 0x7fed77d16dc0] [0] FaceTime HD Camera (Built-in)
[AVFoundation input device @ 0x7fed77d16dc0] [1] Capture screen 0
[AVFoundation input device @ 0x7fed77d16dc0] [2] Capture screen 1
[AVFoundation input device @ 0x7fed77d16dc0] [3] Capture screen 2
[AVFoundation input device @ 0x7fed77d16dc0] AVFoundation audio devices:
[AVFoundation input device @ 0x7fed77d16dc0] [0] Built-in Microphone
8
SSteve 10 may. 2019 a las 23:17

6 respuestas

La mejor respuesta

El problema era que el programa c ++, por alguna razón, no solicitaba acceso a la cámara. Tomé el consejo de @gerwin en los comentarios para intentarlo con Python. Ejecutar ese programa desde la Terminal resultó en que la Terminal solicitara acceso a la cámara. Una vez que concedí eso, el programa c ++ pudo acceder a la cámara cuando se ejecutó desde la Terminal.

En cuanto a CodeRunner, no estoy seguro de cómo hacer que CodeRunner ejecute programas Python en un entorno virtual, por lo que no he podido ejecutar un programa Python OpenCV para solicitar el acceso a la cámara. Así que por el momento no puedo usar CodeRunner para ejecutar un programa en C ++ que accede a la cámara.

3
SSteve 16 may. 2019 a las 19:16

No es una solución definitiva, pero lo resolví instalando cualquier aplicación de terminal que solicite acceso a su cámara. Luego, su programa openCv c ++ obtendrá el acceso a la cámara FaceTime HD después.

Por ejemplo, puede instalar ImageSnap de la siguiente manera:

instalar brew imagesnap

imagesnap -w 1 shot.png

Luego, dale permiso a la cámara a través de la ventana emergente que aparecerá.

2
byiringiro billy 27 sep. 2019 a las 17:36

Encontré una solución para esto:

Primero, restablezca las reglas de su cámara:

tccutil reset Camera

Luego, ejecuté un software de terceros para acceder a la cámara desde la terminal. Al ejecutar lo siguiente:

brew install imagesnap
imagesnap -w 1 snapshot.png

Me preguntaron si quería permitir que el terminal acceda a mi cámara. Hice clic en "Sí". Y ahora mi programa C ++ ahora puede acceder a la cámara desde la terminal.

Nota: Las imágenes mostradas en ZipZit eran muy similares, excepto que no tenía un terminal listado debajo de la cámara.

Pero después de ejecutar un programa de terceros. luego se agregó a la lista.

0
Shawn Swanson 5 jul. 2019 a las 16:24

Versiones: XCode 10.3 , MacOS Mohave 10.14.6 , OpenCV 4.1.1_2

El proyecto OpenCV está en C++

Agregue esta clase a su proyecto:

Encabezado (.h):

class CameraIssue {


public:
    CameraIssue() {}
    ~CameraIssue() {}

    bool dealWithCamera();
};

Archivo .mm. Tenga en cuenta que no es .cpp, es .mm porque queremos operar con AVFoundation

bool CameraIssue::dealWithCamera()
{
    AVAuthorizationStatus st = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (st == AVAuthorizationStatusAuthorized) {
        return true;
    }

    dispatch_group_t group = dispatch_group_create();

    __block bool accessGranted = false;

    if (st != AVAuthorizationStatusAuthorized) {
        dispatch_group_enter(group);
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {

            accessGranted = granted;
            NSLog(@"Granted!");
            dispatch_group_leave(group);
        }];
    }

    dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)));

    return accessGranted;
}

Y antes de acceder a VideoCapture, llame a este método así:

CameraIssue _camIssue;
_camIssue.dealWithCamera(); //do whatever you need with bool return

Quizás se pregunte: ¿por qué estoy creando la clase C++ mientras uso la extensión Objective-C++ (.mm)?

Para crear la clase Objective-C, es posible que deba importar el marco Foundation e importar eso me dio muchos errores sobre símbolos duplicados porque Foundation y las bibliotecas de terceros que estoy usando comparten muchos nombres . Así que creé la clase C++, pero con la extensión .mm para poder importar el marco AVFoundation y otorgar acceso a la cámara.

El método dealWithCamera() está muy lejos de ser perfecto, pero se adapta exactamente a mis necesidades. Siéntase libre de extenderlo, optimizarlo, agregar una devolución de llamada, etc.

1
Eugene Alexeev 19 sep. 2019 a las 08:39

Finalmente pude resolver esto siguiendo una cadena de recomendaciones en Stackoverflow y GitHub. Fue un error doloroso que me quemó el día tratando de hacer que mi código volviera a funcionar a pesar de que funcionaba bien antes de MacOS Mojave.

Solución

Coloque el archivo Info.plist con el campo NSCameraUsageDescription como sugerido en el directorio Productos / Build de su Destino (haga clic con el botón derecho en el producto en el panel izquierdo en el proyecto Xcode y haga clic en "Mostrar en el buscador").

  • Automatice este proceso de copiar / pegar Info.plist en su directorio de compilación (siguiendo esta sugerencia) agregándolo a la lista de Copy Files debajo de Build Phases de su "Destino" y cambiando el Destino a "Directorio de productos" y Subruta a "."

Resultado

  • El binario ejecutable de Target's Unix solicitará permiso para acceder a la Cámara y, al dar su consentimiento, el binario se agregará a la lista de aplicaciones con permiso para acceder a la Cámara disponible en System Preferences > Privacy > Camera.
    • FYI: para forzar la eliminación de esta lista, escriba tccutil reset Camera en Terminal
  • Es posible que deba ejecutar el Objetivo un par de veces antes de que se le solicite permiso / se acceda a la Cámara.

Problema

Instanciar el objeto cv::VideoCapture(0) para acceder a la transmisión de video de la cámara arroja el siguiente error a pesar de que el código se estaba ejecutando bien en la versión de MacOS antes de Mojave

OpenCV: no autorizado para capturar video (estado 0), solicitando ...
OpenCV: ¡la cámara no pudo inicializarse correctamente!

Causa

MacOS Mojave ha reforzado la protección de la privacidad, que ahora requiere que las aplicaciones soliciten explícitamente y soliciten permiso antes de acceder a la cámara como se explica aquí.

Sugerencias que no funcionaron

A continuación, las sugerencias que figuran en varias publicaciones de Stackoverflow no obligaron con éxito al binario creado a solicitar permiso para acceder a la cámara: - Agregar Info.plist a su directorio de Proyecto - Configurar la ruta a Info.plist en Build Settings > Packaging > Info.plist File o - Elegirlo en General > Identity > Choose Info.plist File... de tu objetivo

Sugerencias que podrían haber ayudado

Como se indica en el opencv GitHub cerrado problema, se realizaron algunos cambios en el libopencv alrededor de abril '19 que posiblemente también podría haber facilitado el uso de Info.plist disponible en el directorio de compilación para pedirle al usuario permiso para acceder a la cámara. Así que también actualicé mi opencv a la última versión estable 4.1.0 usando brew upgrade.

PD Estoy ejecutando MacOS Mojave 10.14.5, Xcode 10.2.1 y OpenCV 4.1.0

0
Pacific Stickler 22 jun. 2019 a las 00:50

Estamos teniendo este problema exacto ejecutándose en opencv 4.1.1-pre. Resolvimos el problema volviendo a 4.0.1.

0
Liam 18 jul. 2019 a las 08:00