⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 musicplay.cpp

📁 这是一个用vc编写的系统
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************

 * 文件名:player.cpp

 * 说明  :根据摄像头拍摄的人体动作来演奏音乐

 * Modified by PRTsinghua@hotmail.com

******************************************************************************/



#include "stdafx.h"

#include "MusicPlay.h"



#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif





#include <windows.h>

#include <dshow.h>

#include <stdio.h>

#include <conio.h>

#include <qedit.h>	// SampleGrabber用

#include <math.h>

#include <windowsx.h>

#include <mmsystem.h>

#include <stdlib.h>

#include <string.h>

#include <limits.h>

#include <ctype.h>



#pragma comment(lib, "strmiids.lib")	



#undef  M_PI

#define M_PI 3.1415926535897932

#define HUGE 



#define MAX_FILENAME_SIZE   128



#pragma comment(lib, "winmm.lib")



#define x_size 160

#define y_size 120

#define MAX_CNTR 10000

#define GRAY 128

#define PI 3.14159



// 图像结构

typedef struct{				

	HINSTANCE			hi;

	HWND				hwnd;		// 自己的窗口操作

	BYTE				*lpBmpData;	// BMP数据

	BITMAPINFOHEADER	bih;		// 位图信息

} IMG0;



// WAVE结构

typedef struct waveInst {

	HANDLE hWaveInst;

	HANDLE hWaveHdr;

	HANDLE hWaveData;

} WAVEINST;



typedef WAVEINST FAR *LPWAVEINST;



// 全局变量和函数

int NumDevsOut;

WORD Version;

char		szAppName[]		= "oscillat";	// 应用名

HINSTANCE	hInstApp		= NULL;			// 起动操作

HWND		hwndApp			= NULL;			// 主要窗口的操作

HWND		hwndChild[7]	= {NULL};		// 文件名窗口的操作

HWAVEOUT	hWaveOut		= NULL;

LPWAVEHDR	lpWaveHdr		= NULL;

int		tate;

int		yoko;

int		scale = 1;

long	rec_freq = 44100L;

short	rec_bits = 8;

long	sec = 5;

char	buf[256];

#define	HANON (1.05946309435929526)



DWORD	th_Proc0( void );

LRESULT	CALLBACK grProc0( HWND, UINT, WPARAM, LPARAM );

DWORD	th_Proc1( void );

LRESULT	CALLBACK grProc1( HWND, UINT, WPARAM, LPARAM );



BOOL	initVideo(void);

void	closeVideo(void);

void	initGraphic(void);

void	closeGraphic(void);

void	closeVideo(void);

void	initWindow0(void);

void	initWindow1(void);

void	openWindow0(void);

void	openWindow1(void);

void	masuku(BYTE *);

int		obtain_contour(int x_start, int y_start, unsigned char image[y_size][x_size]);

int		remove_areas(BYTE *);

void	haikei(BYTE *pRGB, BYTE *pRGB0, BYTE *pRGB1); 

void	HSV(double *H, double *S, double *V, double B, double G, double R);

int		remove_areas2(void);



void cleanup(LPWAVEINST lpWaveInst);

void oscillatPlay(int, double);

void oscillatStop(void);

void makedata(DWORD dwDataSize, int pattern, double freq, unsigned char HUGE * lpData);



ICreateDevEnum	*pDevEnum	= NULL;

IGraphBuilder	*pGraph		= NULL;

IMediaControl	*pMC		= NULL;

ICaptureGraphBuilder2	*pCapture = NULL;

IBaseFilter		*pF			= NULL;

ISampleGrabber	*pGrab		= NULL;		// 以上这些变量最后要释放



IMG0	img00, img01;



unsigned char image1[y_size][x_size];

unsigned char image3[y_size][x_size];

unsigned char line[x_size*y_size*3];

int chain_code[MAX_CNTR];

int Freeman[8][2] = 

	{

		{1,0}, {1,-1}, {0,-1}, {-1,-1}, 

		{-1,0}, {-1,1}, {0,1}, {1,1}

	};

int ch_x[2];

int ch_y[2];

int check;

double Z;

int onkai = 0;



CWinApp theApp;



using namespace std;





// 主函数

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])

{

	int nRetCode = 0;



	// 初始化MFC

	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))

	{

		cerr << _T("Fatal Error: MFC initialization failed") << endl;

		nRetCode = 1;

		return nRetCode;

	}

	

	int		X_SIZE, Y_SIZE;

	BYTE	*pRGB0, *pRGB1;

	HRESULT	hr;



	initVideo();	// 视频的初期化

	initGraphic();	// 图像画面的初期化

	initWindow0();	// 视频画面表示的Window的初期化

	initWindow1(); 	// 图像画面表示的Widow的初期化



	printf( "图像输入开始,请按任意键\n" ); 

	getch();

	printf( "图像输入已经开始了,暂时停止 -- q\n" ); 



	// ---- 图像输入开始 ----

	// 制作表示窗口

	openWindow0();

	openWindow1();



	pGrab -> SetBufferSamples(TRUE);	// 开始grab

 	pMC -> Run();						// 开始rendering



	// ***********  追加  ******************

	BYTE *pRGB, *pRGB2;

	Sleep(1000);

	

	printf("记录初期背景图像,按任意键\n");

	getch();

	

	long n = img00.bih.biSizeImage;

	pRGB = (BYTE *)malloc(n);	// pRGB 初期背景图像的排列

	pRGB2 = (BYTE *)malloc(n);	// pRGB 初期背景图像的排列

	if (pRGB == NULL) 

	{

		printf("内存不足(pRGB)\n");

	}

	

	hr = pGrab -> GetCurrentBuffer( &n, (long *)pRGB );

	

	// ********** 到这里为止 ******************



	while(1)

	{

	 	long n = img00.bih.biSizeImage;

		hr = pGrab -> GetCurrentBuffer( &n, (long *)img00.lpBmpData );



		pRGB0	= img00.lpBmpData;

		pRGB1	= img01.lpBmpData;

		X_SIZE	= img00.bih.biWidth;

		Y_SIZE	= img00.bih.biHeight;



		// pRGB0 视频图像的图像排列

		// pRGB1 进行图像处理后的图像的排列

		// 数据的格式,沿着从下到上的方向。

		// 按BGR的顺序排列



		haikei(pRGB, pRGB0, pRGB1);

		masuku(pRGB1);

		remove_areas(pRGB1);



		InvalidateRect( img00.hwnd, NULL, FALSE);	// 输入画像窗口的更新

		InvalidateRect( img01.hwnd, NULL, FALSE);	// 画像窗口的更新



		if( kbhit() )

		{

			getch();

			hr = pMC -> Pause();

			printf("grab停止:结束 - q  、再次打开 - 别的键\n");

			if(getch() == 'q')

				break;

			pMC -> Run();

		}

	}

	

	pMC -> Stop();

	pGrab -> SetBufferSamples( 0 );

	// ---- 结束操作 ---- 

	

	oscillatStop();

	

	closeVideo();

	closeGraphic();



	SendMessage( img00.hwnd, WM_CLOSE, 0, 0 );	// 图像输入窗口结束

	SendMessage( img01.hwnd, WM_CLOSE, 0, 0 );	// 图像表示窗口结束



	return 0;

}





/******************************************************************************

 * 源图像窗口的创建与消息循环

******************************************************************************/

DWORD th_Proc0( void )

{

	MSG msg;



	int sm0 = GetSystemMetrics( SM_CYCAPTION );

	int sm1 = GetSystemMetrics( SM_CXDLGFRAME ); // WS_OVRELAPP的时候,框子的宽度

	int sm2 = GetSystemMetrics( SM_CYDLGFRAME ); // 变成了SM_CYDLGFRAME

	// 创建窗口

	img00.hwnd = CreateWindow( "GRC0",			// 组的名字

				"Source Image",

				WS_OVERLAPPED | WS_VISIBLE,		// 窗口的属性

				0, 100,							// 表示的位置

				img00.bih.biWidth  + sm1 * 2,	// 描绘大小,计算大小

				img00.bih.biHeight + sm0 + sm2 * 2,

				HWND_DESKTOP,

				NULL, img00.hi, NULL 	     );					



	while( GetMessage( &msg, NULL, 0, 0 ) )

	{

		TranslateMessage( &msg );

		DispatchMessage( &msg );

	}



	return 0;

}





/******************************************************************************

 * 处理后图像窗口的创建与消息循环

******************************************************************************/

DWORD th_Proc1( void )

{

	MSG msg;



	int sm0 = GetSystemMetrics( SM_CYCAPTION );

	int sm1 = GetSystemMetrics( SM_CXDLGFRAME ); // WS_OVRELAPP的时候,框子的宽度

	int sm2 = GetSystemMetrics( SM_CYDLGFRAME ); // 变成了SM_CYDLGFRAME

	// 创建窗口

	img01.hwnd = CreateWindow( "GRC1",			// 小组的名字

				"Result Image",

				WS_OVERLAPPED | WS_VISIBLE,		// 窗口的属性

				0, 400,							// 表示的位置

				img01.bih.biWidth  + sm1 * 2,	// 描绘大小 计算大小

				img01.bih.biHeight + sm0 + sm2 * 2,

				HWND_DESKTOP,						

				NULL, img01.hi, NULL 	     );					



	while( GetMessage( &msg, NULL, 0, 0 ) )

	{

		TranslateMessage( &msg );

		DispatchMessage( &msg );

	}



	return 0;

}





/******************************************************************************

 * 窗口的取得,仅仅在再一次的描绘中进行

******************************************************************************/

LRESULT CALLBACK grProc0( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )

{

				

	PAINTSTRUCT	ps;



    switch (msg)

	{

	case WM_PAINT:							// 描绘位图

		BeginPaint( hwnd, &ps );

		SetDIBitsToDevice( ps.hdc, 0, 0,	// 复制刚才x,y的坐标

					img00.bih.biWidth,		// DIB的宽度

					img00.bih.biHeight,		// DIB的高度

					0, 0,					// DIB的坐标 

					0,						// 扫描线

					img00.bih.biHeight,		// 扫描线的数量

					img00.lpBmpData,

					(BITMAPINFO *)&( img00.bih),	// 分派到BITMAPINFO

					DIB_RGB_COLORS );

        EndPaint( hwnd, &ps );

		return 0;



	case WM_DESTROY:

		PostQuitMessage( 0 );				// 结束信息循环

		break;			



	default:

		return DefWindowProc( hwnd, msg, wp, lp );

	}

	

	return 0;	

}





/******************************************************************************

 * 窗口的取得,仅仅在再一次的描绘中进行

******************************************************************************/

LRESULT CALLBACK grProc1( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )

{

				

	PAINTSTRUCT	ps;



    switch (msg)

	{

	case WM_PAINT:							// 描绘位图

		BeginPaint( hwnd, &ps );

		SetDIBitsToDevice( ps.hdc, 0, 0,	// 复制刚才x,y的坐标

					img01.bih.biWidth,		// DIB的宽度

					img01.bih.biHeight,		// DIB的高度

					0, 0,					// DIB的坐标 

					0,						// 扫描线

					img01.bih.biHeight,		// 扫描线的数量

					img01.lpBmpData,

					(BITMAPINFO *)&( img01.bih),	// 分派到BITMAPINFO

					DIB_RGB_COLORS );

        EndPaint( hwnd, &ps );

		return 0;



	case WM_DESTROY:

		PostQuitMessage( 0 );				// 结束信息循环

		break;			



	default:

		return DefWindowProc( hwnd, msg, wp, lp );

	}

	return 0;

	

}





/******************************************************************************

 * 初始化Video

******************************************************************************/

BOOL initVideo(void)

{

	AM_MEDIA_TYPE   amt;



	CoInitialize(NULL);		// COM的初期化



	// ---- 输入计算的准备 ----



	// 搜索输入设备

	IBaseFilter  *pbf = NULL;

	IMoniker * pMoniker = NULL;

    ULONG cFetched;

    

	// 创建输入设备的各个部分

    CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,

					  IID_ICreateDevEnum, (void ** ) &pDevEnum);



    // 设置视频输入设备的各个部分

    IEnumMoniker * pClassEnum = NULL;

    pDevEnum -> CreateClassEnumerator(

					CLSID_VideoInputDeviceCategory, &pClassEnum, 0);

    

	if (pClassEnum == NULL)

	{

		AfxMessageBox("没有发现摄像头,程序将退出!");

		pDevEnum -> Release();

		CoUninitialize();



        return FALSE ;

    }

 

	// 取得最初发现的视频输入设备object的接口

    pClassEnum -> Next(1, &pMoniker, &cFetched);

	pMoniker->BindToObject( 0, 0, IID_IBaseFilter, (void**)&pbf );

 	

	// ---- 过虑图像的准备 ----

    // 创建过虑图像,取得接口

    CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC,

					  IID_IGraphBuilder, (void **) &pGraph);

    pGraph -> QueryInterface( IID_IMediaControl, (LPVOID *) &pMC );

	// 把输入图像追加到过虑图像

    pGraph -> AddFilter( pbf, L"Video Capture");

	// 因为进行了追加所以解除参照的输入图像

    pbf -> Release();



	// ---- 过虑图像的准备 ----

    // 创建过虑图像,取得接口

	CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, 

                      IID_IBaseFilter, (LPVOID *)&pF);

	pF -> QueryInterface( IID_ISampleGrabber, (void **)&pGrab );

	// 把输入图像追加到过虑图像

	ZeroMemory(&amt, sizeof(AM_MEDIA_TYPE));

	amt.majortype  = MEDIATYPE_Video;

	amt.subtype    = MEDIASUBTYPE_RGB24;

	amt.formattype = FORMAT_VideoInfo; 

	pGrab -> SetMediaType( &amt );

	// 把grubber过虑追加到过虑图像

	pGraph -> AddFilter(pF, L"SamGra");



	// ---- 输入图像的准备 ----

	// 创建输入图像   

	CoCreateInstance( CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,

				      IID_ICaptureGraphBuilder2, (void **) &pCapture );

    // 把过虑图像编入到输入图像

    pCapture -> SetFiltergraph( pGraph );

    // 输入图像的设定,设定grubber为rendering输出

    pCapture -> RenderStream (&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,

                                pbf, NULL, pF);

  

	// ---- 表示窗口的准备 ----

	// 位图信息的取得	

	pGrab -> GetConnectedMediaType( &amt ); 

	// 获得视频头部的信息

	VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)amt.pbFormat;

	// 在视频的头部包含位图的信息

	// 把位图的信息复制到BITMAPINFO的结构体中

	BITMAPINFO BitmapInfo;

	ZeroMemory( &BitmapInfo, sizeof(BitmapInfo) );

	CopyMemory( &BitmapInfo.bmiHeader, &(pVideoHeader->bmiHeader), 

				sizeof(BITMAPINFOHEADER));



	img00.bih = BitmapInfo.bmiHeader;

 	long n = img00.bih.biSizeImage;

	

	char s[100];

	sprintf(s, "Video Width: %ld  Video Height: %ld", 

				img00.bih.biWidth, img00.bih.biHeight);

	AfxMessageBox(s);

	

	img00.lpBmpData = (BYTE *)malloc( n );

	

	// ************* 追加 *****************



	if (img00.lpBmpData == NULL) {

		AfxMessageBox("内存不足!");

	}

	

	img00.hi = (HINSTANCE)GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE );

	return true;

}





/******************************************************************************

 * 初始化Graphics

******************************************************************************/

void initGraphic(void)

{

	// 把位图的信息复制到BITMAPINFO的结构体中

	BITMAPINFO BitmapInfo;

	ZeroMemory( &BitmapInfo, sizeof(BitmapInfo) );

	CopyMemory( &BitmapInfo.bmiHeader, &img00.bih, 

				sizeof(BITMAPINFOHEADER));

	img01.bih = BitmapInfo.bmiHeader;

 	long n = img01.bih.biSizeImage;



	img01.lpBmpData = (BYTE *)malloc( n );

	

	// **************** 追加 ******************



	if (img01.lpBmpData == NULL) {

		printf("内存不足 (img01.lpBmpData)\n");

	}



	img01.hi = (HINSTANCE)GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE );

}





/******************************************************************************

 * 关闭Video

******************************************************************************/

void closeVideo(void)

{

    // 接口的解除

    pMC -> Release();		

	pDevEnum -> Release();

    pGraph -> Release();

    pCapture -> Release();

	

	CoUninitialize();



	free( img00.lpBmpData );

}





/******************************************************************************

 * 关闭Graphic

******************************************************************************/

void closeGraphic(void)

{

	free( img01.lpBmpData );

}





/******************************************************************************

 * 初始化窗口0

******************************************************************************/

void initWindow0(void)

{

	// 表示窗口的定义

	WNDCLASSEX	wc;							// 新做成的窗口组

	memset( &wc, 0, sizeof(WNDCLASSEX) );

	wc.cbSize        = sizeof(WNDCLASSEX);	

	wc.lpfnWndProc   = grProc0;				// 取得持有这个组的窗口

	wc.hInstance     = (HINSTANCE)GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE ); 

	wc.lpszClassName = "GRC0";				// 这个组的名字

	wc.cbWndExtra    = 10;					// 确保相关的结构体的特点的范围

	RegisterClassEx( &wc );					// 窗口组的登记



}





/******************************************************************************

 * 初始化窗口1

******************************************************************************/

void initWindow1(void)

{

								// 表示窗口的定义

	WNDCLASSEX	wc;							// 新做成的窗口组

	memset( &wc, 0, sizeof(WNDCLASSEX) );

	wc.cbSize        = sizeof(WNDCLASSEX);	

	wc.lpfnWndProc   = grProc1;				// 取得持有这个组的窗口

	wc.hInstance     = (HINSTANCE)GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE ); 

	wc.lpszClassName = "GRC1";				// 这个组的名字

	wc.cbWndExtra    = 10;					// 确保相关的结构体的特点的范围

	RegisterClassEx( &wc );					// 窗口组的登记

}





/******************************************************************************

 * 打开窗口0

******************************************************************************/

void openWindow0(void)

{

	DWORD tid;



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -