comment utiliser ISampleGrabber

comment utiliser ISampleGrabber - C++ - Programmation

Marsh Posté le 15-04-2008 à 20:31:11    

Bonjour  
Je suis entrain de travailler sur un programme implémenté pour un robot et qui utilise  IvmrWindowlesscontrol9,je veux récupérer l'image de la caméra montée sur le robot pour pouvoir l'utiliser avec une autre fonction qui va la traiter, mais j'arrive pas à réaliser ça, voiçi la partie  
 du code que je viens d'ajouter.  
Au niveau de fichier header j'ai ajouté:  
 
#include "Qedit.h"  // cette line une fois ajouté a généré plusieurs erreurs et je sais pas pourquoi!!!!???    
ISampleGrabber* pGrabber;  
IVMRWindowlesscontrol9* pwc;  
HRESULT GetCurrentBuffer(&size, (long *)pBuffer);  
   
 
Au programme principale j'ai ajouté  
 
if ( camera = RUNNING)  
 
{  
HRESULT hr;  
 
size = x*y*3; //x = height and y = weight  
 
char *pBuffer = new char[size];  
 
hr = pGrabber->GetCurrentBuffer(&size, (long *)pBuffer);  
 
if (FAILED(hr))  
 
AfxMessageBox("Impossible de récupérer le buffer" );  
 
else  
 
Function1(&pGrabber);// Function1 étant la fonction qui va traiter l'image  
 
}  
 
   
Si quelqu'un peut m'aider je serais trés reconnaissante et merci d'avance.


---------------
fedora6
Reply

Marsh Posté le 15-04-2008 à 20:31:11   

Reply

Marsh Posté le 15-04-2008 à 23:23:35    

Il faut connecter la source à la pin d'entrée de l'ISampleGrabber (en ayant spécifié le format du média désiré) puis connecter la sortie de l'ISampleGrabber a un renderer.

Reply

Marsh Posté le 16-04-2008 à 06:20:45    


Bonjour bjone,
Merci de m'avoir répondre mais est-ce que vous pouvez m'expliquer comment faire exactement je suis nulle en C++, quelle modification dois-je aujouter pour que ça fonctionne.

Reply

Marsh Posté le 16-04-2008 à 13:30:38    

bin en fait à voir le code, je m'attendais a cette réponse :D
 
Il te faut le Platform SDK (Windows 2003), dedans tu auras le graphedit, et par exemple dans le graphedit en ouvrant un média, tu verras le graphe directshow construit automatiquement.
 
tu pourras ajouter des filtres intermédiaires et jouer avec les connections des pins, ça te donnera une représentation mentale de comment ça marche, ce qui est obligatoire avant d'essayer de coder quoique ce soit.
 
ensuite commence a potasser la doc:
http://msdn2.microsoft.com/en-us/l [...] S.85).aspx
 
Comme essai à coder, l'idée est d'abord de commencer par instancier une source, instancier un renderer, puis de connecter les deux avec le gestionnaire de graphe.  
puis d'incruster des filtres (dont le ISampleGrabber)

Message cité 1 fois
Message édité par bjone le 16-04-2008 à 13:31:00
Reply

Marsh Posté le 19-05-2008 à 22:22:26    

bjone a écrit :

bin en fait à voir le code, je m'attendais a cette réponse :D
 
Il te faut le Platform SDK (Windows 2003), dedans tu auras le graphedit, et par exemple dans le graphedit en ouvrant un média, tu verras le graphe directshow construit automatiquement.
 
tu pourras ajouter des filtres intermédiaires et jouer avec les connections des pins, ça te donnera une représentation mentale de comment ça marche, ce qui est obligatoire avant d'essayer de coder quoique ce soit.
 
ensuite commence a potasser la doc:
http://msdn2.microsoft.com/en-us/l [...] S.85).aspx
 
Comme essai à coder, l'idée est d'abord de commencer par instancier une source, instancier un renderer, puis de connecter les deux avec le gestionnaire de graphe.  
puis d'incruster des filtres (dont le ISampleGrabber)


Bonjour  :hello:  
J'ai besoin d'aide car j'ai toujours des problémes avec le SampleGrabber.
voila une partie de mon code source:
Les déclarations:  

Code :
  1. long pBufferSize;
  2. unsigned char* pBuffer;
  3. unsigned char* buffer=0;
  4. unsigned char size = 640*576*3;
  5. unsigned int gWidth=0;
  6. unsigned int gHeight=0;
  7. unsigned int gChannels=0;


 
La fonction CaptureVideo() qui se charge de caputrer la video et qui fait appel à la fonction GrabData() qui me permet de récupérer le buffer(vers la fin de la fontion):  

Code :
  1. HRESULT CCaptureVideo::CaptureVideo()
  2. {
  3. HRESULT hr;
  4.     IBaseFilter *pSrcFilter=NULL;
  5.     // Get DirectShow interfaces
  6.     hr = GetInterfaces();
  7. if (FAILED(hr))
  8.     {
  9.         DisplayMesg(TEXT("Failed to get video interfaces!  hr=0x%x" ), hr);
  10.         return hr;
  11.     }
  12.     // Attach the filter graph to the capture graph
  13.     hr = m_pCapture->SetFiltergraph(m_pGraph);
  14.     if (FAILED(hr))
  15.     {
  16.         DisplayMesg(TEXT("Failed to set capture filter graph!  hr=0x%x" ), hr);
  17.         return hr;
  18.     }
  19.     // Use the system device enumerator and class enumerator to find
  20.     // a video capture/preview device, such as a desktop USB video camera.
  21. hr = FindCaptureDevice(&pSrcFilter);
  22.     if (FAILED(hr))
  23.     {
  24.         // Don't display a message because FindCaptureDevice will handle it
  25.         return hr;
  26.     }
  27. if( bDevCheck == FALSE)
  28. {
  29.  return E_FAIL;
  30. }
  31.     // Add Capture filter to our graph.
  32.     hr = m_pGraph->AddFilter(pSrcFilter, L"Video Capture" );
  33.     if (FAILED(hr))
  34.     {
  35.         DisplayMesg(TEXT("Couldn't add the capture filter to the graph!  hr=0x%x\r\n\r\n" )
  36.             TEXT("If you have a working video capture device, please make sure\r\n" )
  37.             TEXT("that it is connected and is not being used by another application.\r\n\r\n" ), hr);
  38.         pSrcFilter->Release();
  39.         return hr;
  40.     }
  41. // Create the Sample Grabber.
  42.          hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
  43.                                       IID_IBaseFilter, (void**) & pGrabberF);
  44.         if (FAILED(hr)) {
  45.                 return hr;
  46.       }
  47.         hr = m_pGraph->AddFilter(pGrabberF, L"Sample Grabber" );
  48.         if (FAILED(hr)) {
  49.                 return hr;
  50.      }
  51.         pGrabberF->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber);
  52.    
  53.         AM_MEDIA_TYPE mt;
  54.         ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
  55.         mt.majortype = MEDIATYPE_Video;
  56.         mt.subtype = MEDIASUBTYPE_RGB24;
  57.         hr = pGrabber->SetMediaType(&mt);
  58.         if (FAILED(hr)) {
  59.                 return hr;
  60.   }
  61.         hr = pGrabber->SetOneShot(FALSE);
  62.         hr = pGrabber->SetBufferSamples(TRUE);
  63.        hr = pSrcFilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp);
  64. ConfigRenderer();
  65. // Add Renderer filter to our graph.
  66.     hr = m_pGraph->AddFilter(pVmr, L"VMR9" );
  67.     // Render the preview pin on the video capture filter
  68.     // Use this instead of m_pGraph->RenderFile
  69.     hr = m_pCapture->RenderStream (&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
  70.                                    pSrcFilter,pGrabberF, pVmr);
  71.     if (FAILED(hr))
  72.     {
  73.         DisplayMesg(TEXT("Couldn't render the video capture stream.  hr=0x%x\r\n" )
  74.             TEXT("The capture device may already be in use by another application.\r\n\r\n" )
  75.             TEXT("The sample will now close." ), hr);
  76.         pSrcFilter->Release();
  77.         return hr;
  78.     }
  79.         hr = pGrabber->GetConnectedMediaType(&mt);
  80.         if (FAILED(hr)) {
  81.                 return hr;
  82.         }
  83.         VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER *)mt.pbFormat;
  84.         gChannels = pVih->bmiHeader.biBitCount / 8;
  85.         gWidth = pVih->bmiHeader.biWidth;
  86.         gHeight = pVih->bmiHeader.biHeight;
  87.     // Now that the filter has been added to the graph and we have
  88.     // rendered its stream, we can release this reference to the filter.
  89.     pSrcFilter->Release();
  90. #ifdef REGISTER_FILTERGRAPH
  91.     // Add our graph to the running object table, which will allow
  92.     // the GraphEdit application to "spy" on our graph
  93.     hr = AddGraphToRot(m_pGraph, &m_dwGraphRegister);
  94.     if (FAILED(hr))
  95.     {
  96.         DisplayMesg(TEXT("Failed to register filter graph with ROT!  hr=0x%x" ), hr);
  97.         m_dwGraphRegister = 0;
  98.     }
  99. #endif
  100.     // Start previewing video data
  101.     hr = m_pMC->Run();
  102.     if (FAILED(hr))
  103.     {
  104.         DisplayMesg(TEXT("Couldn't run the graph!  hr=0x%x" ), hr);
  105.         return hr;
  106.     }
  107.     // Remember current state
  108.       m_psCurrent = RUNNING;
  109. FILE *stream;
  110.   buffer = new unsigned char[size];
  111. for(int i=0;i<5;i++)
  112. {
  113.   Sleep(100);
  114.   buffer = GrabData();
  115.   if (buffer!=NULL)
  116.   {
  117.     stream=fopen("c:\somefile.txt","w+" );
  118.  //fwrite(buffer,3,sizeof(buffer),stream);
  119.     fprintf(stream,"%s",buffer);
  120.  fclose(stream);
  121.   }
  122. }
  123.   unsigned char image=GetImage();
  124.     return S_OK;
  125. }


La fonction GrabData() qui me permet de récupérer le buffer:

Code :
  1. unsigned char* CCaptureVideo::GrabData()
  2. {
  3. HRESULT hr;
  4.    if (pGrabber == 0)
  5.                 return 0;
  6.         long Size = 0;
  7.         hr = pGrabber->GetCurrentBuffer(&Size, NULL);
  8.         if (FAILED(hr))
  9.                 return 0;
  10.         else if (Size != pBufferSize) {
  11.                 pBufferSize = Size;
  12.                 if (pBuffer != 0)
  13.                         delete[] pBuffer;
  14.                 pBuffer = new unsigned char[pBufferSize];
  15.         }
  16.         hr = pGrabber->GetCurrentBuffer(&pBufferSize, (long*)pBuffer);
  17.         if (FAILED(hr))
  18.  {
  19.                 return 0;
  20.  }
  21.         else {
  22.    return pBuffer;               
  23.  }
  24. }


La fonction qui me permet de lire une bitmap:

Code :
  1. unsigned char * CCaptureVideo::LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
  2. {
  3.     FILE *filePtr;    // Le pointeur du fichier
  4.     BITMAPFILEHEADER bitmapFileHeader;    // En-tête du fichier bitmap
  5.     unsigned char *bitmapImage; // Données du fichier bitmap
  6.     int imageIdx = 0; // image index counter
  7.     unsigned char tempRGB; // Variable temporaire de permutation BGR -> RGB
  8.     // Ouvre le fichier en lecture binaire
  9.     filePtr = fopen(filename, "rb" );
  10.     if (filePtr == NULL)
  11. { // Si l'ouverture du fichier ne s'est pas dérouler correctement, on quitte la fonction
  12.  return NULL;    // On quitte la fonction en renvoyant un NULL
  13. }
  14.     // Lecture de l'en-tête de fichier
  15.     fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
  16.     // On vérifie que le fichier est bien de type Bitmap
  17.     if (bitmapFileHeader.bfType != BITMAP_ID)
  18.     {
  19.         fclose(filePtr);    // Fermeture du fichier
  20.         return NULL;    // On quitte la fonction en renvoyant NULL
  21.     }
  22.     // Lecture des l'en-tête d'informations du Bitmap
  23.     fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
  24.     // Vérification de la compression. Doit être égal à BI_RGB
  25.     if (bitmapInfoHeader->biCompression != BI_RGB)
  26.     {
  27.         fclose(filePtr);    // Fermeture du fichier
  28.         return NULL;    // On quitte la fonction en renvoyant NULL
  29.     }
  30.     // Allocation de la mémoire pour contenir les données de l'image
  31.     bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
  32.     // On vérifie l'allocation de la mémoire
  33.     if (!bitmapImage)
  34.     {
  35.         free(bitmapImage);    // Libération de la mémoire
  36.         fclose(filePtr);    // Fermeture du fichier
  37.         return NULL;    // Renvoie de NULL
  38.     }
  39.     // On place le pointeur du fichier au début des données du bitmap
  40.     fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
  41.     // Lecture des données de l'image
  42.     fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
  43.     // On s'assure que les données de l'image aient bien été lues
  44.     if (bitmapImage == NULL)
  45.     {
  46.         fclose(filePtr);    // Fermeture du fichier
  47.         return NULL;    // Renvoie de NULL
  48.     }
  49.     // Inversion du rouge et du bleu BGR -> RGB
  50.     for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3)
  51.     {
  52.         tempRGB = bitmapImage[imageIdx];
  53.         bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
  54.         bitmapImage[imageIdx + 2] = tempRGB;
  55.     }
  56.     fclose(filePtr);    // Fermeture du fichier
  57.     return bitmapImage;    // Renvoie des données de l'image
  58. }


La fonction qui me permet d'écrire une bitmap:

Code :
  1. BOOL CCaptureVideo::WriteBitmapFile(char *filename, int width, int height, unsigned char *imageData)
  2. {
  3.     FILE *filePtr; // Pointeur de fichier
  4.     BITMAPFILEHEADER bitmapFileHeader; // En-tête de fichier
  5.     BITMAPINFOHEADER bitmapInfoHeader; // En-tête d'informations
  6.     unsigned char tempRGB; // Variable temporaire pour changer BGR -> RGB
  7.     // Ouverture du fichier en mode écriture binaire
  8.     filePtr = fopen(filename, "wb" );
  9.     if (!filePtr)
  10.         return FALSE;
  11.     // Définition de tous les champs des en-tête
  12.     // En-tête de fichier BITMAPFILEHEADER
  13.     bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER);
  14.     bitmapFileHeader.bfType = 0x4D42;
  15.     bitmapFileHeader.bfReserved1 = 0;
  16.     bitmapFileHeader.bfReserved2 = 0;
  17.     bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
  18.     // En-tête d'informations
  19.     bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
  20.     bitmapInfoHeader.biPlanes = 1;
  21.     bitmapInfoHeader.biBitCount = 24;
  22.     bitmapInfoHeader.biCompression = BI_RGB;
  23.     bitmapInfoHeader.biSizeImage = width * abs(height) * 3;
  24.     bitmapInfoHeader.biXPelsPerMeter = 0;
  25.     bitmapInfoHeader.biYPelsPerMeter = 0;
  26.     bitmapInfoHeader.biClrUsed = 0;
  27.     bitmapInfoHeader.biClrImportant = 0;
  28.     bitmapInfoHeader.biWidth = width;
  29.     bitmapInfoHeader.biHeight = height;
  30.     // Inversion des composants RGB -> BGR  
  31.     for (unsigned int i = 0; i < bitmapInfoHeader.biSizeImage; i += 3)
  32.     {
  33.         tempRGB = imageData[i];
  34.         imageData[i] = imageData [i + 2];
  35.         imageData[i + 2] = tempRGB;
  36.     }
  37.     // Ecriture de l'en-tête de fichier  
  38.     fwrite(&bitmapFileHeader, 1, sizeof(BITMAPFILEHEADER), filePtr);
  39.     // Ecriture de l'en-tête d'informations  
  40.     fwrite(&bitmapInfoHeader, 1, sizeof(BITMAPINFOHEADER), filePtr);
  41.     // Ecriture des données de l'image  
  42.     fwrite(imageData, 1, bitmapInfoHeader.biSizeImage, filePtr);
  43.        
  44.     fclose(filePtr);    // fermeture du fichier
  45.     return TRUE;
  46. }


La fonction GetIamge():

Code :
  1. unsigned char CCaptureVideo::GetImage()
  2. {
  3. FILE* stream;
  4. BITMAPINFOHEADER bitmapInfoHeader;
  5. unsigned char* bitmapData;
  6. bitmapData = LoadBitmapFile("C:\search.bmp", &bitmapInfoHeader);
  7. if(bitmapData!=0)
  8. {
  9. bool write;
  10. write = WriteBitmapFile("c:\imagewrite",760,576,bitmapData);
  11. stream = fopen("wahiba.txt","w+" );
  12. fprintf(stream,"%s",bitmapData);
  13. fclose(stream);
  14. }
  15. return (unsigned char)bitmapData;
  16. }


 
Au début je veux bien m'excuser d'avoir envoyé tout à la fois.
Mes problémes sont les suivants:
1. le buffer récupérer par la fonction GrabData() n'est pas de taille fixe, j'essaye de l'écrire dans un fichier texte et le nombre des caractéres écrits est considérablement variable(entre 12000 et 180000), alors je pense qu'il n'est pas entrain de récupérer une image car la taille doit être fixe (largeur*hauteur*3(RGB)=640*576*3)
alors je voulais savoir où est le probléme et si mon raisonnement est correcte ou pas???????
 
2. Alors vu que la récupération du buffer est bloquée et que je dois avancé dans la projet j'ai essayé de lire une image sur le disque dûr pour pouvoir continuer par la suite(j'ai besoin d'une image pour le reste du projet) alors j'utilise la fonction LoadBitmap avec une image enregistrée dans le repertoire du projet et d'essayer de la écrire dans un fichier juste pour vérifier et de la réecrire une autre fois avec la fonction WriteBitmap, le probléme est que cette fonction fonctionne correctement une fois dans un fichier .cpp tout seule(contenant uniquement LoadbitmapFile, WritebitmapFile et GetImage) mais dans mon programme le fichier
 contenant l'image ne s'ouvre même pas(j'ai vérifié le chemin).
 
Alors si vous pouvez m'aider je serai vraiment trés reconnaissante  :jap: et merci d'avance.


---------------
fedora6
Reply

Marsh Posté le 20-05-2008 à 21:59:45    

Difficile de t'aiguiller.
 
sinon déjà:
unsigned char size = 640*576*3;  
KABOOOM :D
 
il me semble que chez ms il y a des exemples de capture d'une frame vidéo.
 
moi je me sers de directshow pour récuper l'audio de medias inconnus pour les position en OpenAl.
pas tourné autour de la capture précise d'une frame.
dans mon cas, je récupère aussi des buffers variables de samples audio, que je mets bout à bout.
 
dans le cas d'une capture de frame, il y a certainement des états qui permette de savoir quand tu as récupéré une frame entière.
 

Reply

Marsh Posté le 21-05-2008 à 11:28:42    

Pour le:
unsigned char size = 640*576*3;  
je l'ai utilisé parceque il m'a semblé que je dois spécifier le taille du buffer(l'imposé en quelque sorte) parceque la taille récupérée est notamment plus pétite que la taille réelle mais cela a donné le même résultat.
Je veux dire que même avant d'utiliser ce unsigned char size = 640*576*3; le probléme existait.
Alors je vais préciser une question:
Pour la fonction LoadBitmapFile j'arrive m^me pas à ouvrir le fichier de l'image dans mon programme alors que lorsque je l'ai utilisé dans u fichier .cpp à part ça a fonctionné à quoi est due cela vous pensez??? j'ai vérifié le chemin.


---------------
fedora6
Reply

Marsh Posté le 21-05-2008 à 13:27:54    

j'ai pas bien compris l'explication, mais pour être plus clair un unsigned char est limité à 255, donc ton 640*576*3 dépasse. (donc int ou unsigned int)  
 
après effectivement pour tes chemins, \ doit être traduit par \\  
genre "C:\search.bmp" ça doit être "c:\\search.bmp"
 
sinon ta fonction GetImage() pourrait juste retourner un bool pour indiquer le succès ou l'échec.
 
sinon:
stream = fopen("wahiba.txt","w+" );
fprintf(stream,"%s",bitmapData);
fclose(stream);
 
je suppose que c'est pour du débuggage voir si ça vit ?
mais bon avec un %s, t'ira pas bien loin (si y'a un octet à 0 dans les premiers pixels) ou t'ira trop loin (si y'a pas d'octet à 0 tu sors du buffer), donc c'est un peu voir totallement crade.
 
aussi essaye d'utiliser les iostreams.


Message édité par bjone le 21-05-2008 à 13:38:02
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed