mercredi 9 octobre 2013

Récupérer les images d'un appareil photo en PowerShell

Introduction
La société où je travaille va remonter un vrai catalogue informatisé et nous investissons beaucoup de temps dans la structuration des informations... vive les bases de données.
Mais pour faire un catalogue, il faut aussi des images. 
Pourquoi, donc, ne pas essayer d'automatiser la saisie de ces images catalogue directement depuis notre logiciel (nous avons 2500+ produits au catalogue)..

On place l'objet a photographier sur le stand de photographie, on sélectionne l'article dans le programme et ont clique sur le bouton shoot! Prise de photo, traitement d'image (principalement réduction de taille et poids) et stockage peuvent facilement être automatiser pour un travail d'envergure.

Ha oui, pour corser le tout... le soft est maintenu en clipper compilé en 32 bit sous Windows à l'aide d'Harbour Project

Les appareils "moyen de gamme" c'est super
La plupart des appareil photo moyen de gamme sont reconnu comme de vrai lecteurs disques dès qu'il sont branchés en USB. Sur la plupart il est même possible de faire des prises de vues pendant qu'il est branché en USB.
Même, si dans ce cas, il faut faire les prises de vues en poussant sur le bouton, le fait de disposer d'un système de fichier standard est vachement pratique... car un simple "file copy" rempli toutes nos attentes.

Les appareils "haut de gamme" c'est le casse tête
Par contre, les prise de vue seront faite à l'aide d'un Nikon D5000.
Si l'appareil est super et produit des photographies a tomber par terre, les photos ne sont pas accessibles au travers d'un lecteurs.
Si vous branchez le cable USB, Windows reconnait l'appareil et vous pouvez naviguer à la recherche des photographie avec l'explorateur de fichier... faire un copier/coller.

Mais essayer seulement d'écrire un batch ou un programme qui fait un file copy des fichiers jpeg!!!! vous allez voir que les choses se corsent.

Les appareils haut de gamme sont souvent reconnu par Windows et y associe une interface de gestion "plus évoluée"... cela implique souvent la perte de fonctionnalités de base.

La solution se trouve dans l'interface ActiveX WIA.

Qu'est-ce que WIA
WIA signifie Windows Image Acquisition, c'est une interface d'automation qui permettra de capturer et transférer des images depuis différentes sources (Appareil Photo, WebCam, Scanner, etc).
Avec WIA il est même possible de déclencher la prise de vue sur l'appareil.
Vous trouverez probablement assez facilement des informations sur WIA en naviguant sur le net.

WIA et PowerShell
Il est possible d'utiliser WIA avec PowerShell... c'est bien pratique pour récupérer des images stockées sur notre Nikon D5000.
L'exemple MyShotDownloadPict.ps1 ci-dessous fait une capture d'image (prise de vue) puis rapatrie toutes les images dans un répertoire local du PC... finalement, il effaces ces images de la carte SD (pour la séance suivante).

// Script Powershell pour:
// 
// Utiliser WIA Windows Image Acquisition Automation afin de
// prendre commander le shoot d'une photo (avec Nikon D5000) 
// connecté en USB puis transférer toutes les photos (dont le
// shoot) dans un répertoire sur le PC.
// 
// Nécessite l'enregistrement de WIA 
//   RegSvr32 WIAAut.dll
//
// Source: 
//   http://helvick.blogspot.be/2007/08/camera-automation-with-powershell-part_19.html
//   http://msdn.microsoft.com/fr-fr/library/bb469890.aspx
//
$ErrorActionPreference="silentlycontinue"
$WIAManager = new-object -comobject WIA.DeviceManager
if (!$?) {
   write "Unable to Create a WIA Object"
   Eexit
}
$DeviceList = $WIAManager.DeviceInfos
if ($DeviceList.Count -gt 0) {
   $Device=$DeviceList.item($DeviceList.Count)
} else {
   write "No Device Connected"
}
$ConnectedDevice = $Device.connect()
if (!$?) {
   write "Unable to Connect to Device"
   Exit
}
$Commands = $ConnectedDevice.Commands
$TakeShot="Not Found"
foreach ($item in $Commands) {
   if ($item.name -match "take") {
       $TakeShot=$item.CommandID
   }
}


$Pdir="C:\Stock\Input\CatPhoto.In"
new-item $Pdir -itemtype dir
$ICompare="c:\Program Files\ImageMagick-6.3.5-Q16\compare.exe"
$ActiveCamera = $ConnectedDevice

# Fait un shot et télécharge l'image
$ActiveCamera.ExecuteCommand($TakeShot)
# Attendre 1 seconde pour que l'appareil
# Ai le temps d'enregistrer l'image sur la carte
sleep 1

# Télécharger le restant des images éventuellement présente
$iCount= $ActiveCamera.items.Count
Write "Camera has $iCount pictures"
for ($iCount=$ActiveCamera.items.Count;$iCount -gt 0;$iCount--) {
    
    $f=$ActiveCamera.items.item($iCount)
    $fg=$f.Transfer()
    $localFilename = "pict_"+$(get-date -f "yyyyMMdd_hhmmss")+"_$iCount.jpg"
    Write "Saving $localFilename..."
    $fg.SaveFile( $Pdir+"\"+$localFilename )

    # Retire l'image de la carte de l'appareil photo
    $ActiveCamera.items.Remove($iCount)
}

Voici donc un outil d'automatisation que je pourrais appeler depuis mon programme Clipper (ouf!)

Aucun commentaire: