[PYTHON] Aperçu de la caméra QR code

Cet article a été confirmé pour fonctionner dans les environnements suivants.

version
NAOqi 2.5.5.5
Choregraphe 2.5.5.5

Laissez Pepper lire le code QR en douceur

Pepper a un mécanisme pour reconnaître facilement le code QR. Lorsque le code QR est reconnu, l'événement BarcodeReader / BarcodeDetected est déclenché et le résultat reconnu peut être utilisé.

fig1.png Sélectionnez un événement mémoire et connectez-le à la box que vous souhaitez recevoir

La reconnaissance de code QR est facile à mettre en œuvre, mais les utilisateurs craignent de bien la tenir car ils ne peuvent pas voir en temps réel le code QR qu'ils présentent aux yeux de Pepper. Il devrait être plus facile à utiliser si vous pouvez afficher l'image de la caméra sur l'écran et vérifier comment l'image est affichée sur le côté Pepper en temps réel. (Cette méthode est souvent utilisée pour les applications Robo créées par Softbank Robotics.) Cependant, contrairement à la reconnaissance de code QR, la prévisualisation de l'appareil photo n'est pas facile à réaliser. Softbank Robotics Ryutaro Murayama, Satoshi Tanizawa, Kazuhiko Nishimura "Programmation Pepper de l'opération de base à la planification et à la production d'applications" J'ai extrait la partie pertinente et créé un échantillon simplifié, je voudrais donc expliquer le mécanisme.

Exemple de programme

Veuillez télécharger l'exemple de programme depuis GitHub.  https://github.com/Atelier-Akihabara/pepper-qrpreview-example

Lorsque vous exécutez l'exemple, vous verrez quelque chose comme ce qui suit. fig2.png

--Lorsque le code QR est reconnu, l'application sera fermée.

Structure du programme

Le programme a le flux suivant.

1. Côté poivre

a. Pour utiliser l'affichage, utilisez [Show App] pour afficher le HTML. b. Accédez à la caméra de Pepper. c. Obtenez le nom abonné pour recevoir les données. d. Passez l'identifiant d'abonné reçu au côté affichage via ALMemory.

2. Côté écran

Créez un gestionnaire pour recevoir le SubscriberId envoyé du côté Pepper. b. Recevoir les données d'image de la caméra en utilisant le nom abonné reçu par le gestionnaire créé. c. Dessinez les données d'image de la caméra reçues à l'aide de Canvas. Exécutez d. B. C. autant de fois que nécessaire.

Côté poivre

Nous suivrons le processus du côté Pepper. Du côté de Pepper, il s'agit de transmettre le nom d'abonné requis pour l'acquisition d'image au côté d'affichage.

1-a. Pour utiliser l'affichage, utilisez [Show App] pour afficher le code HTML suivant (index.html).

index.html


<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="initial-scale = 1, minimum-scale = 1, maximum-scale = 1" />
    <link rel="stylesheet" type="text/css" href="main.css">
    <script src="/libs/qimessaging/2/qimessaging.js"></script>
    <script src="scripts/jquery-2.2.2.min.js"></script>
    <script src="scripts/adjust23.js"></script>
    <script src="scripts/main.js"></script>
      </head>
  <body onLoad="startSession();">
    <div class="container">
        <div id="camera" class="panel inactive">
            <div class="canvas-container">
                <div class="canvas-background">
                    <canvas id="canvas" width="80" height="60"></canvas>
                </div>
            </div>
        </div>
    </div>
    <div class="abort-container inactive" id="common">
        <div class="abort-button" id="abort">Suspension</div>
    </div>
  </body>
</html>

Ce à quoi vous devez faire attention ici est <canvas id =" canvas "width =" 80 "height =" 60 "> </ canvas>. Une image de caméra est dessinée dans cette zone. <script src =" scripts / main.js "> </ script> contient le processus de dessin suivant. startSession () est la fonction de démarrage du processus de dessin. Le fait est que vous avez besoin d'une boîte (canevas) pour l'afficher.

1-b, c. Voir [root / QR Preview / Subscribe Camera].

python


self.subscriberId = self.videoDevice.subscribeCamera("QRPreview",
                    0, # TopCamera
                    7, # AL:kQQQVGA
                    0, # AL::kYuvColorSpace
                    fps)

ʻALVideoDevice :: subscribeCamera est appelé pour obtenirsubscriberId`. Les arguments sont organisés dans l'ordre suivant:

Nom Contenu
Name Nom
CameraIndex Index de la caméra (0 ou caméra frontale)
Resolution Constante (constante AL) indiquant la résolution de la caméra:7 correspondant à kQQQVGA, QQQVGA est de 80x60 pixels)
ColorSpace Format d'image obtenu à partir de la caméra (constante AL::0 correspondant à kYuvColorSpace, YuvColorSpace n'est que le signal de luminosité de l'espace colorimétrique YUV)
Fps Fréquence d'images requise

Consultez ce qui suit pour les constantes définies dans divers paramètres.  http://doc.aldebaran.com/2-5/family/pepper_technical/video_pep.html

La valeur de retour de subscribeCamera sera dans self.subscriberId. Vous pouvez désormais accéder aux données de votre caméra.

Remarque: Les constantes commençant par ʻAL :: k` sont exprimées en langage C ++, elles doivent donc être des nombres concrets côté Python.

1-d. Veuillez continuer à voir [root / QR Preview / Subscribe Camera].

python


self.memory.raiseEvent("ProgrammingPepperSample/PreviewMode", self.subscriberId)

Avec ce code, passez le subscriptionId obtenu précédemment via ʻALMemoryau côté affichage. Du côté de l'affichage, cetabonnéId` est utilisé pour extraire les données à dessiner depuis la caméra.

Côté écran

C'est enfin côté affichage. Comme le traitement du dessin ne peut pas être effectué du côté Pepper, le traitement des pixels est requis sur JavaScript du côté affichage.

2-a. Voir main.js.

main.js


ALMemory.subscriber("ProgrammingPepperSample/PreviewMode").then(function(subscriber) {
    subscriber.signal.connect(function(subscriberId) {
        if(subscriberId.length > 0) {
            console.log("Subscribing...: " + subscriberId)
            previewRunning = true
            activatePanel("camera")
            activatePanel("common")
            getImage(ALVideoDevice, subscriberId)
        }else{
            previewRunning = false
            inactivatePanel("camera")
            inactivatePanel("common")
        }
    })
});

Ici, il s'agit de laisser le processus getImage (ALVideoDevice, subscriptionId). Lorsque «ProgrammingPepperSample / PreviewMode» vole, getImage (ALVideoDevice, subscriptionId) `est appelé. D'autres fonctions appelées en interne ne font que changer d'éléments sur le HTML.

2-b, c. C'est finalement le processus de dessin. Il est traité par la fonction getImage ().

main.js


function getImage(ALVideoDevice, subscriberId) {
    ALVideoDevice.getImageRemote(subscriberId).then(function (image) {
        if(image) {
            var imageWidth = image[0];
            var imageHeight = image[1];
            var imageBuf = image[6];
            console.log("Get image: " + imageWidth + ", " + imageHeight);

            if (!context) {
                context = document.getElementById("canvas").getContext("2d");
            }
            if (!imgData || imageWidth != imgData.width || imageHeight != imgData.height) {
                imgData = context.createImageData(imageWidth, imageHeight);
            }
            var data = imgData.data;

            for (var i = 0, len = imageHeight * imageWidth; i < len; i++) {
                var v = imageBuf[i];
                data[i * 4 + 0] = v;
                data[i * 4 + 1] = v;
                data[i * 4 + 2] = v;
                data[i * 4 + 3] = 255;
            }

            context.putImageData(imgData, 0, 0);
        }
        
        if(previewRunning) {
            setTimeout(function() { getImage(ALVideoDevice, subscriberId) }, 100)
        }
    })
}

ʻAl VideoDevice.getImageRemote` reçoit les données d'image de Pepper. Les données d'image (image) sont transmises dans la structure suivante.

Contenu
[0] Taille horizontale
[1] Taille verticale
[2] Nombre de couches
[3] Espace colorimétrique
[4] Horodatage(seconds).
[5] Horodatage(microseconds).
[6] Tableau binaire de données d'image
[7] ID de la caméra
[8] Informations sur l'angle gauche de la caméra(radian).
[9] Informations d'angle sur la caméra(radian).
[10] Informations sur l'angle droit de la caméra(radian).
[11] Informations sur l'angle sous la caméra(radian).

Les informations requises sont les informations de [6], c'est-à-dire les données d'image.

Ici, l'initialisation (création d'une image vierge) pour dessiner sur le canevas est effectuée.

python


if (!context) {
    context = document.getElementById("canvas").getContext("2d");
}
if (!imgData || imageWidth != imgData.width || imageHeight != imgData.height) {
    imgData = context.createImageData(imageWidth, imageHeight);
}

Ensuite, dessinez les données via putImageData.

python


context.putImageData(imgData,x,y);

x et y sont les coordonnées pour commencer à dessiner. Puisque le point de départ est 0, 0, spécifiez 0 pour x et y. Dans imageData, le tableau de données à dessiner sera placé dans le tableau dans l'ordre RGBA. R est rouge, G est vert, B est bleu et A est le canal alpha. Les données de caméra obtenues de Pepper sont des informations de luminosité, donc si vous entrez la même valeur pour chaque RVB, vous pouvez obtenir une image monochrome. Puisque A est un canal alpha, entrez 255 afin qu'il ne soit pas transparent.

python


for (var i = 0, len = imageHeight * imageWidth; i < len; i++) {
    var v = imageBuf[i];
    data[i * 4 + 0] = v;
    data[i * 4 + 1] = v;
    data[i * 4 + 2] = v;
    data[i * 4 + 3] = 255;
}

Vous pouvez maintenant dessiner une image fixe ci-dessus. 2-d. Les images doivent être constamment mises à jour.

python


setTimeout(function() { getImage(ALVideoDevice, subscriberId) }, 100)

Il fonctionne de manière récursive et dessine.

finalement

Avez-vous compris le déroulement de l'affichage de l'aperçu de la caméra sur l'écran Pepper? Le but est d'obtenir le subscriptionId et d'effectuer le processus de dessin sur le côté d'affichage. L'échantillon a une très faible résolution de QQQVGA (80x60), mais vous pouvez également obtenir des images à des résolutions plus élevées. De plus, bien que l'échantillon soit monochrome, vous pouvez également obtenir une image couleur en modifiant le format et la routine de dessin. Cependant, c'est JavaScript sur HTML qui effectue le processus de dessin. Si vous dessinez à haute résolution ou effectuez un traitement couleur, le traitement risque de ne pas pouvoir suivre. Essayez de trouver un paramètre qui fonctionne confortablement sur l'application créée.

Recommended Posts

Aperçu de la caméra QR code
Affichage du code QR
Commande pour générer un code QR
Générer du code QR en Python
Décrypter le code QR avec CNN
[Python] Générer un code QR en mémoire
Générer du code QR à l'aide du "qrcode" de Python