web-dev-qa-db-fra.com

Enregistrer une image dans OpenCV

Je suis nouveau sur OpenCV et j'essaie de capturer une image, puis de l'enregistrer dans un fichier. Je poste le code pour votre référence, ci-dessous.

Le fichier jpg est en cours d’enregistrement, mais il est noir.

// Capture the Image from the webcam
CvCapture *pCapturedImage = cvCreateCameraCapture(0);

// Get the frame
IplImage *pSaveImg = cvQueryFrame(pCapturedImage);

// Save the frame into a file
cvSaveImage("test.jpg". ,pSaveImg); // A JPG FILE IS BEING SAVED
                                    // OF 6KB , BUT IT IS BLACK

Toutes les fonctions sont réussies. J'ai essayé le code ci-dessus dans XP et Vista - le résultat est une image noire sur les deux. S'il vous plaît laissez-moi savoir ce que je manque.

24
Sujay Ghosh

Si vous utilisez C++, il est préférable de utiliser l'interface C++ :

using namespace cv;
// Capture the Image from the webcam
VideoCapture cap(0);

// Get the frame
Mat save_img; cap >> save_img;

if(save_img.empty())
{
  std::cerr << "Something is wrong with the webcam, could not get frame." << std::endl;
}
// Save the frame into a file
imwrite("test.jpg", save_img); // A JPG FILE IS BEING SAVED
19
Barnabas Szabolcs

D'après mon expérience, OpenCV écrit une image en noir lorsque SaveImage reçoit une matrice avec une profondeur de bits différente de 8 bits. En fait, c'est en quelque sorte documenté:

Seulement 8 bits à canal unique ou à 3 canaux (avec l'ordre des canaux ‘BGR’) les images peuvent être enregistré en utilisant cette fonction. Si la Le format, la profondeur ou l’ordre des canaux est différent, utilisez cvCvtScale et cvCvtColor pour le convertir avant save, ou utilisez universal cvSave à enregistrer l'image au format XML ou YAML.

Dans votre cas, vous pouvez d’abord rechercher quel type d’image est capturé, modifier les propriétés de capture (je suppose que CV_CAP_PROP_CONVERT_RGB peut être important) ou le convertir manuellement ultérieurement.

Voici un exemple de conversion en représentation 8 bits avec OpenCV. cc voici une matrice originale de type CV_32FC1, cc8u est sa version mise à l'échelle qui est réellement écrite par SaveImage:

# I want to save cc here
cc8u = CreateMat(cc.rows, cc.cols, CV_8U)
ccmin,ccmax,minij,maxij = MinMaxLoc(cc)
ccscale, ccshift = 255.0/(ccmax-ccmin), -ccmin
CvtScale(cc, cc8u, ccscale, ccshift)
SaveImage("cc.png", cc8u)

(désolé, c'est du code Python, mais il devrait être facile de le traduire en C/C++)

5
sastanin

Parfois, le premier appel à cvQueryFrame () renvoie une image vide. Essayer:

IplImage *pSaveImg = cvQueryFrame(pCapturedImage);
pSaveImg = cvQueryFrame(pCapturedImage);

Si cela ne fonctionne pas, essayez de sélectionner le périphérique de capture automatiquement:

CvCapture *pCapturedImage = cvCreateCameraCapture(-1);

Ou vous pouvez essayer de sélectionner d'autres périphériques de capture où n = 1,2,3 ...

CvCapture *pCapturedImage = cvCreateCameraCapture(n);

PS: De plus, je crois qu’il ya un malentendu à propos de l’image capturée en regardant votre nom de variable. La variable pCapturedImage n'est pas une image, c'est une capture. Vous pouvez toujours "lire" une image de capture.

5
nimcap

désolé si c'est trop évident. Êtes-vous sûr que la webcam est correctement vue et détectée par OpenCV En d'autres termes, obtenez-vous une image lorsque vous redirigez le cadre capturé vers une fenêtre "highGui"? Par exemple, comme ceci:

 frame = cvQueryFrame( capture );
 cvNamedWindow( "myWindow", CV_WINDOW_AUTOSIZE );
 cvShowImage( "myWindow", frame );
3
david h

Je connais le problème! Vous venez de mettre un point après "test.jpg"!

cvSaveImage ("test.jpg"., pSaveImg);

Je peux me tromper mais je pense que ce n'est pas bon!

3
lf.

J'ai eu le même problème avec ma Microsoft WebCam. J'ai regardé dans la boîte à outils d'acquisition d'images de Matlab et constaté que la résolution maximale prise en charge était de 640 * 480. 

Je viens de changer le code dans openCV et ajouté

cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 352); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 288);

avant la fonction cvQueryFrame qui était la résolution prise en charge suivante et qui a changé, certaines images initiales ont été ignorées avant d’enregistrer l’image et enfin de la faire fonctionner.

Je partage mon code de travail

#include "cv.h" 
#include "highgui.h" 
#include <stdio.h> 



using namespace cv;
using namespace std;

int main() 
{
CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 352); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 288)


 // Get one frame
IplImage* frame;

for (int i = 0; i < 25; i++) 
{
frame = cvQueryFrame( capture );
}


printf( "Image captured \n" );  
//IplImage* RGB_frame = frame;
//cvCvtColor(frame,RGB_frame,CV_YCrCb2BGR);
//cvWaitKey(1000);
cvSaveImage("test.jpg" ,frame);
//cvSaveImage("cam.jpg" ,RGB_frame);

printf( "Image Saved \n" );

//cvWaitKey(10);

// Release the capture device Housekeeping
cvReleaseCapture( &capture );
//cvDestroyWindow( "mywindow" );
return 0;
}

Mes suggestions

  1. Ne saisissez pas d'image avec la résolution maximale
  2. Ignorer des images pour une initialisation correcte de la caméra
2

J'ai eu le même problème sur Windows Vista, je viens d'ajouter ce code avant cvQueryFrame:

cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 720);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);
1
jmp4281

J'utilise le code suivant pour capturer des images:

CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
if(!capture) error((char*)"No Capture");
IplImage *img=cvQueryFrame(capture);

Je sais que cela fonctionne à coup sûr

1
Yogi

SayntLewis a raison. Lorsque vous activez l'appareil photo avec cvCaptureFromCAM, la balance des blancs automatique n'est pas encore ajustée (processus lent), de sorte que vous risquez d'obtenir un blanc ou un noir (en fonction des conditions d'éclairage) sur les premières images . La même chose se produit quand il y a un changement soudain de la foudre de la scène . Attendez juste un moment après avoir ouvert l'appareil photo, videz la mémoire tampon et vous êtes prêt à partir.

1
Vitor

Je vous suggère d'exécuter OpenCV checkness check

C’est une série de petits exécutables situés dans le répertoire bin d’opencv.

Il va vérifier si votre appareil photo est ok

1
Eric

Désolé de faire apparaître un ancien message, mais je voulais fournir une autre réponse à quiconque rencontre ce sujet.

J'ai eu le même problème. Peu importe ce que je faisais, l'image ressemblait à un noir complet. J'ai essayé de faire plusieurs appels consécutifs à cvQueryFrame et j'ai remarqué que lorsque j'en faisais 5 ou plus, je pouvais voir l'image. J'ai donc commencé à supprimer les appels un par un pour voir où se trouvait le "point de rupture". Ce que j'ai fini par trouver, c'est que l'image est devenue de plus en plus sombre au fur et à mesure que je retirais chaque appel. Faire un seul appel donnait une image presque complètement noire, mais si je regardais de très près, je pourrais distinguer mon image.

J'ai essayé 10 appels consécutifs pour tester ma théorie, et bien sûr, on m'a donné une image très lumineuse, étant donné que je suis dans une pièce sombre. Espérons que c’était le même problème que vous rencontriez.

Je ne connais pas grand chose en imagerie, mais il semble que plusieurs appels consécutifs à cvQueryFrame augmentent la durée d'exposition de l'appareil photo. Cela résout définitivement le problème, même si cela ne semble pas être la solution la plus élégante. Je vais voir si je peux trouver un paramètre qui augmentera l'exposition, ou peut-être un autre paramètre qui éclaircira mes images.

Bonne chance!

1
SayntLewis

Sur OSX, enregistrer des images vidéo et des images fixes ne fonctionnait pour moi que lorsque je donnais un chemin complet à cvSaveImage:

cvSaveImage("/Users/nicc/image.jpg",img);
0
nicc

je pense que la caméra ne s’initialise pas dans la première image ... Essayez d’enregistrer l’image après 10 images.

0
chronos

j'espère que cela sauvera les images de votre webcam 

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
   VideoCapture cap(0);

   Mat save_img;

   cap >> save_img;

   char Esc = 0;

   while (Esc != 27 && cap.isOpened()) {        
    bool Frame = cap.read(save_img);        
    if (!Frame || save_img.empty()) {       
        cout << "error: frame not read from webcam\n";      
        break;                                              
    }
    namedWindow("save_img", CV_WINDOW_NORMAL);  
    imshow("imgOriginal", save_img);            
    Esc = waitKey(1);
}
imwrite("test.jpg",save_img); 
}
0
Haris Hussain