Skip to content

Instantly share code, notes, and snippets.

@wrongbranch
Last active January 18, 2021 04:21
Show Gist options
  • Save wrongbranch/12ac9b16f449a54ba9dc9e3ec1e5b907 to your computer and use it in GitHub Desktop.
Save wrongbranch/12ac9b16f449a54ba9dc9e3ec1e5b907 to your computer and use it in GitHub Desktop.
DirectShow_Graph_OpenCV.cpp
/*
DirectShow_Graph_OpenCV.cpp
see also DirectShow_Graph_trap_OpenCV.cpp
*/
#define UNICODE
#define _UNICODE
#include <wchar.h>
#define WIN32_LEAN_AND_MEAN
#define _WIN32_DCOM
#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#include <dshow.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// download qedit.h and edit it
#include <qedit.h> // CLSID_SampleGrabber ISampleGrabber IID_ISampleGrabber
// use CV_PI instead of M_PI
// #define _USE_MATH_DEFINES
#include <opencv2/opencv.hpp>
int main(int ac, char **av)
{
HRESULT hr = CoInitialize(NULL);
if(FAILED(hr)){
fprintf(stderr, "CoInitialize Failed\n");
return 1;
}
ICreateDevEnum *pDevEnum = NULL;
CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void **)&pDevEnum);
IEnumMoniker *pClassEnum = NULL;
pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pClassEnum, 0);
if(!pClassEnum){
fprintf(stderr, "Device does not exist\n");
pDevEnum->Release();
CoUninitialize();
return 2;
}
// find Nth filter
IBaseFilter *pbf = NULL;
for(int c = 0; c < 3; ++c){
if(pbf){ pbf->Release(); pbf = NULL; }
ULONG cFetched;
IMoniker *pMoniker = NULL;
if(pClassEnum->Next(1, &pMoniker, &cFetched) == S_OK){
pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pbf);
pMoniker->Release();
}
}
pClassEnum->Release();
pDevEnum->Release();
if(!pbf){
fprintf(stderr, "Video Capture Filter not found\n");
CoUninitialize();
return 3;
}
IGraphBuilder *pGraph = NULL;
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **)&pGraph);
pGraph->AddFilter(pbf, L"Video Capture");
IBaseFilter *pF = NULL;
CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (LPVOID *)&pF);
ISampleGrabber *pGrab = NULL;
pF->QueryInterface(IID_ISampleGrabber, (void **)&pGrab);
AM_MEDIA_TYPE amt;
ZeroMemory(&amt, sizeof(AM_MEDIA_TYPE));
amt.majortype = MEDIATYPE_Video;
amt.subtype = MEDIASUBTYPE_RGB24; // check
amt.formattype = FORMAT_VideoInfo;
pGrab->SetMediaType(&amt);
pGraph->AddFilter(pF, L"Grabber");
ICaptureGraphBuilder2 *pCapture = NULL;
CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,
IID_ICaptureGraphBuilder2, (void **)&pCapture);
pCapture->SetFiltergraph(pGraph);
pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
pbf, NULL, pF);
IMediaControl *pMC = NULL;
pGraph->QueryInterface(IID_IMediaControl, (LPVOID *)&pMC);
pMC->Run(); // start render
pGrab->SetBufferSamples(TRUE); // Grab
pGrab->GetConnectedMediaType(&amt);
fprintf(stdout, "amt.lSampleSize = %dbytes\n", amt.lSampleSize);
VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER *)amt.pbFormat;
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(bmi));
BITMAPINFOHEADER *pH = &bmi.bmiHeader;
CopyMemory(pH, &pVIH->bmiHeader, sizeof(BITMAPINFOHEADER));
fprintf(stdout, "%dx%d %dbits\n", pH->biWidth, pH->biHeight, pH->biBitCount);
// OpenCV from here
// only 24bit support
cv::namedWindow("Src", CV_WINDOW_AUTOSIZE | CV_WINDOW_FREERATIO);
cv::namedWindow("Diff", CV_WINDOW_AUTOSIZE | CV_WINDOW_FREERATIO);
cv::Mat frm(pH->biHeight, pH->biWidth, CV_8UC3);
cv::Mat imgBkg(pH->biHeight, pH->biWidth, CV_8UC3);
cv::Mat imgDiff(pH->biHeight, pH->biWidth, CV_8UC3);
int cnt = 0, bkg = 0;
while(1){
hr = pGrab->GetCurrentBuffer((long *)&pH->biSizeImage, (long *)frm.data);
if(FAILED(hr)){ if(cv::waitKey(50) == 'q') break; else continue; }
#if 0
// im->origin 0: left-top, 1: left-bottom
IplImage *im = cvCreateImage(cvSize(frm.cols, frm.rows), IPL_DEPTH_8U, 3);
if(!im->origin) cv::flip(frm, frm, 0); // reverse top <-> bottom
cvReleaseImage(&im);
#else
cv::flip(frm, frm, 0); // reverse top <-> bottom
#endif
cv::imshow("Src", frm);
if(++bkg == 1) frm.copyTo(imgBkg);
// cv::subtract(frm, imgBkg, imgDiff); // mask=noArray(), dtype=-1
cv::absdiff(frm, imgBkg, imgDiff); // differential
cv::imshow("Diff", imgDiff);
int k = cv::waitKey(10);
if(k == 'q') break;
switch(k){
case 'c': {
char fname[2048];
sprintf(fname, "c:\\temp\\src_%06d.png", cnt);
fprintf(stdout, "save [%s]\n", fname);
cv::imwrite(fname, frm);
sprintf(fname, "c:\\temp\\bkg_%06d.png", cnt);
fprintf(stdout, "save [%s]\n", fname);
cv::imwrite(fname, imgBkg);
sprintf(fname, "c:\\temp\\diff_%06d.png", cnt);
fprintf(stdout, "save [%s]\n", fname);
cv::imwrite(fname, imgDiff);
++cnt;
} break;
case 'b': frm.copyTo(imgBkg); break;
default: break; // skip
}
}
cv::destroyAllWindows();
// OpenCV end
pMC->Release(); // Filter Graph
pCapture->Release(); // Capture Graph
pGrab->Release();
pF->Release(); // Sample Grabber
pGraph->Release();
pbf->Release(); // Capture Filter
CoUninitialize();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment