Last active
January 18, 2021 04:21
-
-
Save wrongbranch/12ac9b16f449a54ba9dc9e3ec1e5b907 to your computer and use it in GitHub Desktop.
DirectShow_Graph_OpenCV.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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