Something More for Research

Explorer of Research #HEMBAD

Combining DirectShow with OpenCV

Posted by Hemprasad Y. Badgujar on January 10, 2015


First, the DirectShow SDK is part of the Windows 7 SDK, so you have to download that.  Once you download that, you have to go into this folder:  C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\multimedia\directshow\baseclasses
and open and compile the baseclasses project.

The header files you need to include (shown in my sample code) are in that directory.  The DirectShow libraries you need to link to are:  Strmbasd.lib, winmm.lib, and Msacm32.lib.  These are located in the same  directory (within a subfolder).

Below is my sample code.  I actually used two cameras at the same time, but it shouldn’t be too hard to remove the second one from the code.  Note that the cameras are selected based on their USB address and verified with their camera names.  You’ll have to change that, but again, not too tough.  The code checks every connected camera, so you can use breaks to find your USB addresses/camera names.

#include <stdio.h>
#include <atlstr.h>
#include <streams.h>
#include <dshow.h>
#include <qedit.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <opencv/cxcore.h>

void setCameraMode(ICaptureGraphBuilder2 *pCaptureGraphBuilder2, IAMStreamConfig *pConfig, IBaseFilter *pDeviceFilter, HRESULT hr)
{
// Set res, frame rate, and color mode
hr = CoInitialize(0);
hr = pCaptureGraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE, 0, pDeviceFilter, IID_IAMStreamConfig, (void**)&pConfig);

int iCount = 0, iSize = 0;
hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);

// Check the size to make sure we pass in the correct structure.
if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
{
// Use the video capabilities structure.

for (int iFormat = 0; iFormat < iCount; iFormat++)
{
VIDEO_STREAM_CONFIG_CAPS scc;
AM_MEDIA_TYPE *pmtConfig;
hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
if (SUCCEEDED(hr))
{
/* Examine the format, and possibly use it. */
if ((pmtConfig->majortype == MEDIATYPE_Video) &&
(pmtConfig->subtype == MEDIASUBTYPE_RGB24) &&
(pmtConfig->formattype == FORMAT_VideoInfo) &&
(pmtConfig->cbFormat >= sizeof (VIDEOINFOHEADER)) &&
(pmtConfig->pbFormat != NULL))
{
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
// pVih contains the detailed format information.
LONG lWidth = pVih->bmiHeader.biWidth;
LONG lHeight = pVih->bmiHeader.biHeight;
}
if (iFormat == 26) { //2 = ‘1280x720YUV’ YUV, 22 = ‘1280x800YUV’, 26 = ‘1280x720RGB’
hr = pConfig->SetFormat(pmtConfig);
}
// Delete the media type when you are done.
DeleteMediaType(pmtConfig);
}
}
}
}
void setCameraControl(IBaseFilter *pDeviceFilter, HRESULT hr, int exposure, int focus)
{
// Query the capture filter for the IAMCameraControl interface.
IAMCameraControl *pCameraControl = 0;
hr = pDeviceFilter->QueryInterface(IID_IAMCameraControl, (void**)&pCameraControl);
if (FAILED(hr))
{
// The device does not support IAMCameraControl
}
else
{
long Min, Max, Step, Default, Flags, Val;

// Get the range and default values
hr = pCameraControl->GetRange(CameraControl_Exposure, &Min, &Max, &Step, &Default, &Flags);
hr = pCameraControl->GetRange(CameraControl_Focus, &Min, &Max, &Step, &Default, &Flags);
if (SUCCEEDED(hr))
{
hr = pCameraControl->Set(CameraControl_Exposure, exposure, CameraControl_Flags_Manual ); // Min = -11, Max = 1, Step = 1
hr = pCameraControl->Set(CameraControl_Focus, focus, CameraControl_Flags_Manual );
}
}
}
void setCameraProperties(IBaseFilter *pDeviceFilter, HRESULT hr, int brightness, int backLightCompensation, int contrast, int saturation, int sharpness, int whiteBalance)
{
// Query the capture filter for the IAMVideoProcAmp interface.
IAMVideoProcAmp *pProcAmp = 0;
hr = pDeviceFilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp);
if (FAILED(hr))
{
// The device does not support IAMVideoProcAmp
}
else
{
long Min, Max, Step, Default, Flags, Val;

// Get the range and default values
hr = pProcAmp->GetRange(VideoProcAmp_Brightness, &Min, &Max, &Step, &Default, &Flags);
hr = pProcAmp->GetRange(VideoProcAmp_BacklightCompensation, &Min, &Max, &Step, &Default, &Flags);
hr = pProcAmp->GetRange(VideoProcAmp_Contrast, &Min, &Max, &Step, &Default, &Flags);
hr = pProcAmp->GetRange(VideoProcAmp_Saturation, &Min, &Max, &Step, &Default, &Flags);
hr = pProcAmp->GetRange(VideoProcAmp_Sharpness, &Min, &Max, &Step, &Default, &Flags);
hr = pProcAmp->GetRange(VideoProcAmp_WhiteBalance, &Min, &Max, &Step, &Default, &Flags);
if (SUCCEEDED(hr))
{
hr = pProcAmp->Set(VideoProcAmp_Brightness, 130, VideoProcAmp_Flags_Manual);
hr = pProcAmp->Set(VideoProcAmp_BacklightCompensation, 0, VideoProcAmp_Flags_Manual);
hr = pProcAmp->Set(VideoProcAmp_Contrast, 4, VideoProcAmp_Flags_Manual);
hr = pProcAmp->Set(VideoProcAmp_Saturation, 100, VideoProcAmp_Flags_Manual);
hr = pProcAmp->Set(VideoProcAmp_Sharpness, 0, VideoProcAmp_Flags_Manual);
hr = pProcAmp->Set(VideoProcAmp_WhiteBalance, 2800, VideoProcAmp_Flags_Manual);
}
}
}
IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir)
{
BOOL       bFound = FALSE;
IEnumPins  *pEnum;
IPin       *pPin;

pFilter->EnumPins(&pEnum);
while(pEnum->Next(1, &pPin, 0) == S_OK)
{
PIN_DIRECTION PinDirThis;
pPin->QueryDirection(&PinDirThis);
if (bFound = (PinDir == PinDirThis))
break;
pPin->Release();
}
pEnum->Release();
return (bFound ? pPin : 0);
}

int main()
{
// for playing
IGraphBuilder *pGraphBuilder;
ICaptureGraphBuilder2 *pCaptureGraphBuilder2;
IMediaControl *pMediaControl = NULL;

// multiple cameras
IBaseFilter *pDeviceFilter_0 = NULL;
IBaseFilter *m_pGrabber_0 = NULL;
ISampleGrabber *m_pGrabberSettings_0 = NULL;
IBaseFilter *pDeviceFilter_45 = NULL;
IBaseFilter *m_pGrabber_45 = NULL;
ISampleGrabber *m_pGrabberSettings_45 = NULL;

// select camera
ICreateDevEnum *pCreateDevEnum = NULL;
IEnumMoniker *pEnumMoniker = NULL;
IMoniker *pMoniker = NULL;
ULONG nFetched = 0;
// initialize COM
CoInitialize(NULL);

// selecting a device
// Create CreateDevEnum to list device
std::string USB1 = "\\\\?\\usb#vid_045e&pid_076d&mi_00#7&1ba27d43&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\global";
std::string USB2 = "\\\\?\\usb#vid_045e&pid_076d&mi_00#7&8e8cc9e&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\global";

CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (PVOID *)&pCreateDevEnum);

// Create EnumMoniker to list VideoInputDevice
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0);
if (pEnumMoniker == NULL) {
// this will be shown if there is no capture device
printf("no device\n");
return 0;
}

// reset EnumMoniker
pEnumMoniker->Reset();

// get each Moniker
while (pEnumMoniker->Next(1, &pMoniker, &nFetched) == S_OK) {
IPropertyBag *pPropertyBag;
TCHAR devname[256];
TCHAR devpath[256];

// bind to IPropertyBag
pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropertyBag);

VARIANT var;

// get FriendlyName
var.vt = VT_BSTR;
pPropertyBag->Read(L"FriendlyName", &var, 0);
WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, devname, sizeof(devname), 0, 0);
VariantClear(&var);

// get DevicePath
// DevicePath : A unique string
var.vt = VT_BSTR;

pPropertyBag->Read(L"DevicePath", &var, 0);

WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, devpath, sizeof(devpath), 0, 0);
std::string devpathString = devpath;

if ((devname[0] == ‘M’) && (devname[21] == ‘5’) && (devpathString == USB1 ))
{
pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pDeviceFilter_0 );
}
if ((devname[0] == ‘M’) && (devname[21] == ‘5’) && (devpathString == USB2 ))
{
pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pDeviceFilter_45 );
}

pMoniker->Release();
pPropertyBag->Release();

if (pDeviceFilter_0 == NULL)
{
MessageBox(NULL, "No MS HD-5000 cameras found", "No cameras", MB_OK);
return 0;
}

}

// create FilterGraph and CaptureGraphBuilder2
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (LPVOID *)&pGraphBuilder);
CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (LPVOID *)&pCaptureGraphBuilder2);

HRESULT hr = CoInitialize(0);
IAMStreamConfig *pConfig = NULL;
setCameraMode(pCaptureGraphBuilder2,  pConfig,  pDeviceFilter_0,  hr); // FPS, Res, color mode
setCameraControl(pDeviceFilter_0, hr, -11, 12); // Focus, exposure
setCameraProperties(pDeviceFilter_0, hr, 130, 0, 4, 100, 0, 2800); // Brightness, saturation, etc
setCameraMode(pCaptureGraphBuilder2,  pConfig,  pDeviceFilter_45,  hr);
setCameraControl(pDeviceFilter_45, hr, -11, 12);
setCameraProperties(pDeviceFilter_45, hr, 130, 0, 4, 100, 0, 2800);

// set grabber properties
AM_MEDIA_TYPE mt;
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&m_pGrabber_0); // create ISampleGrabber
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&m_pGrabber_45);
pCaptureGraphBuilder2->SetFiltergraph(pGraphBuilder); // set FilterGraph
pGraphBuilder->QueryInterface(IID_IMediaControl, (LPVOID *)&pMediaControl); // get MediaControl interface

m_pGrabber_0->QueryInterface(IID_ISampleGrabber, (void**)&m_pGrabberSettings_0);
m_pGrabber_45->QueryInterface(IID_ISampleGrabber, (void**)&m_pGrabberSettings_45);
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24;
hr = m_pGrabberSettings_0->SetMediaType(&mt);
hr = m_pGrabberSettings_45->SetMediaType(&mt);
if (FAILED(hr))
{
return hr;
}
hr = m_pGrabberSettings_0->SetOneShot(FALSE);
hr = m_pGrabberSettings_0->SetBufferSamples(TRUE);
hr = m_pGrabberSettings_45->SetOneShot(FALSE);
hr = m_pGrabberSettings_45->SetBufferSamples(TRUE);

// build filter graph
pGraphBuilder->AddFilter(pDeviceFilter_0, L"Device Filter");
pGraphBuilder->AddFilter(m_pGrabber_0, L"Sample Grabber");
IPin* pSourceOut_0 = GetPin(pDeviceFilter_0, PINDIR_OUTPUT);
IPin* pGrabberIn_0 = GetPin(m_pGrabber_0, PINDIR_INPUT);
pGraphBuilder->Connect(pSourceOut_0, pGrabberIn_0);

pGraphBuilder->AddFilter(pDeviceFilter_45, L"Device Filter");
pGraphBuilder->AddFilter(m_pGrabber_45, L"Sample Grabber");
IPin* pSourceOut_45 = GetPin(pDeviceFilter_45, PINDIR_OUTPUT);
IPin* pGrabberIn_45 = GetPin(m_pGrabber_45, PINDIR_INPUT);
pGraphBuilder->Connect(pSourceOut_45, pGrabberIn_45);

long pBufferSize = 2764800;
unsigned char* pBuffer_0 = 0;
unsigned char* pBuffer_45 = 0;
pBuffer_0 = new unsigned char[pBufferSize];
pBuffer_45 = new unsigned char[pBufferSize];

// start playing
pMediaControl->Run();

// without this messagebox, the graph will be stopped immediately

while (1) {

if (MessageBox(NULL, "Grab frame?", "Grab?", MB_OKCANCEL) == 2)
{
break;
}

hr = m_pGrabberSettings_0->GetCurrentBuffer(&pBufferSize, (long*)pBuffer_0);
hr = m_pGrabberSettings_45->GetCurrentBuffer(&pBufferSize, (long*)pBuffer_45);

Cleanup:

// convert to OpenCV format
IplImage* img_0 = cvCreateImage(cvSize(1280,720),IPL_DEPTH_8U,3);
IplImage* img_45 = cvCreateImage(cvSize(1280,720),IPL_DEPTH_8U,3);
for (int i = 0; i < pBufferSize; i++)
{
img_0->imageData[i] = pBuffer_0[i];
}
cvFlip(img_0, NULL, 0);

for (int i = 0; i < pBufferSize; i++)
{
img_45->imageData[i] = pBuffer_45[i];
}
cvFlip(img_45, NULL, 0);

// show
cvNamedWindow("mainWin_0", CV_WINDOW_AUTOSIZE);
cvMoveWindow("mainWin_0", 100, 100);
cvShowImage("mainWin_0", img_0 );
cvNamedWindow("mainWin_45", CV_WINDOW_AUTOSIZE);
cvMoveWindow("mainWin_45", 100, 100);
cvShowImage("mainWin_45", img_45 );
//cvWaitKey(0);
cvReleaseImage(&img_0 );
cvReleaseImage(&img_45 );
}

// release
pMediaControl->Release();
pCaptureGraphBuilder2->Release();
pGraphBuilder->Release();
pEnumMoniker->Release();
pCreateDevEnum->Release();

// finalize COM
CoUninitialize();

return 0;
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Extracts from a Personal Diary

dedicated to the life of a silent girl who eventually learnt to open up

Num3ri v 2.0

I miei numeri - seconda versione

ThuyDX

Just another WordPress.com site

Algunos Intereses de Abraham Zamudio Chauca

Matematica, Linux , Programacion Serial , Programacion Paralela (CPU - GPU) , Cluster de Computadores , Software Cientifico

josephdung

thoughts...

Tech_Raj

A great WordPress.com site

Travel tips

Travel tips

Experience the real life.....!!!

Shurwaat achi honi chahiye ...

Ronzii's Blog

Just your average geek's blog

Karan Jitendra Thakkar

Everything I think. Everything I do. Right here.

VentureBeat

News About Tech, Money and Innovation

Chetan Solanki

Helpful to u, if u need it.....

ScreenCrush

Explorer of Research #HEMBAD

managedCUDA

Explorer of Research #HEMBAD

siddheshsathe

A great WordPress.com site

Ari's

This is My Space so Dont Mess With IT !!

%d bloggers like this: