Machine vision example from last week’s lecture

Here’s the unedited code from the machine vision worked example we went through in class last week. It’s pretty rough as it is, but I’ll be polishing it up a little bit over the next week or so to make it more adaptible for re-use in other projects.

//
// camera.c - bare bones machine vision engine
// Written by Ted Burke, Last updated 25-10-2012
// ted.burke@dit.ie, batchloaf.wordpress.com
//
// To compile with MinGW:
//	gcc -o camera.exe camera.c -lvfw32
//

#include <windows.h>
#include <vfw.h>
#include <stdio.h>

// Window handles
HWND hWnd;
HWND hWndCap;

int capture_w = 640;
int capture_h = 480;
int capture_device = 0;	// default capture device

int counter = 0;

LRESULT CALLBACK frame_callback(HWND hWndCap, LPVIDEOHDR lpVHdr)
{
	fprintf(stderr, ".");

	LPBYTE p = lpVHdr->lpData;
	int w = capture_w;
	int h = capture_h;

	int x, y, angle;

	for (y=50;y<h-50;++y)
	{
		p[3*y*w + 3*50] = 255;
		p[3*y*w + 3*50 + 1] = 255;
		p[3*y*w + 3*50 + 2] = 255;
		p[3*y*w + 3*(w-50)] = 255;
		p[3*y*w + 3*(w-50) + 1] = 255;
		p[3*y*w + 3*(w-50) + 2] = 255;
	}

	// Check colour of centre pixel
	int g = p[3*(h/2)*w + 3*(w/2) + 1];
	int r = p[3*(h/2)*w + 3*(w/2) + 2];
	if (g > r)
	{
		angle = 30;
	}
	else
	{
		angle = 120;
	}
	y = h/2 - 5;
	while(y < h/2 + 5)
	{
		x = w/2 - 5;
		while (x < w/2 + 5)
		{
			// Change one pixel
			p[3*y*w + 3*x] = 0;
			if (g>r)
			{
				p[3*y*w + 3*x + 1] = 255;
				p[3*y*w + 3*x + 2] = 0;
			}
			else
			{
				p[3*y*w + 3*x + 1] = 0;
				p[3*y*w + 3*x + 2] = 255;
			}
			x = x + 1;
		}
		y = y + 1;
	}

	// Look for minimum brightness inside the box
	int i, min = 255 + 255 + 255;
	int min_x = 0, min_y = 0;

	y = 50;
	while(y < h-50)
	{
		x = 50;
		while (x < w-50)
		{
			// Check one pixel
			i = p[3*y*w + 3*x] + p[3*y*w + 3*x + 1] + p[3*y*w + 3*x + 2];
			if (i < min)
			{
				min = i;
				min_x = x;
				min_y = y;
			}
			x = x + 1;
		}
		y = y + 1;
	}

	y = min_y - 5;
	while(y < min_y + 5)
	{
		x = min_x - 5;
		while (x < min_x + 5)
		{
			// Change one pixel
			p[3*y*w + 3*x] = 255;
			p[3*y*w + 3*x + 1] = 0;
			p[3*y*w + 3*x + 2] = 0;
			x = x + 1;
		}
		y = y + 1;
	}

	// Calculate angle from min_y
	//angle = min_y / 3;

	// Send out an angle to the servo
	char command[100];
	counter = counter + 1;
	if (counter == 10)
	{
		fprintf(stderr,  "SerialSend.exe \\\\.\\COM22 s%04d\n", 10 * angle);
		sprintf(command, "SerialSend.exe \\\\.\\COM22 s%04d", 10 * angle);
		system(command);
		counter = 0;
	}
}

// Message handling function
LRESULT CALLBACK WndProc(
HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
		case WM_TIMER:
			// Save DIB snapshot, then exit from program
			capGrabFrame(hWndCap);
			capFileSaveDIB (hWndCap, "pic.dib");
			DestroyWindow(hWnd);
			break;
		case WM_CLOSE:
			DestroyWindow(hWnd);
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, msg, wParam, lParam);
	}
	return 0;
}

int WINAPI WinMain(
	HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	// Register window class
	WNDCLASSEX wc;
	wc.cbSize        = sizeof(WNDCLASSEX);
	wc.style         = 0;
	wc.lpfnWndProc   = WndProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hInstance;
	wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = "cameraWindowClass";
	wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

	if(!RegisterClassEx(&wc))
		fprintf(stderr, "Window Registration Failed!");

	// Create main window
	hWnd = CreateWindowEx(
		WS_EX_CLIENTEDGE,
		"cameraWindowClass",
		"camera",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		capture_w + 100, capture_h + 100,
		NULL, NULL, hInstance, NULL);
	if (hWnd == NULL)
		fprintf(stderr, "Couldn't create main window.");

	// Create capture window
	hWndCap = capCreateCaptureWindow(
		NULL, WS_CHILD,
		0, 0, capture_w, capture_h,
		hWnd, 0);
	if (hWndCap == NULL)
		fprintf(stderr, "Couldn't create capture window.");

	// Connect to capture driver and set resolution
	capDriverConnect(hWndCap, capture_device);
	DWORD dwSize = capGetVideoFormatSize(hWndCap);
	LPBITMAPINFO lpbi = (LPBITMAPINFO)malloc(dwSize);
	capGetVideoFormat(hWndCap, lpbi, dwSize);
	lpbi->bmiHeader.biWidth = capture_w;
	lpbi->bmiHeader.biHeight = capture_h;
	capSetVideoFormat(hWndCap, lpbi, dwSize);
	free(lpbi);

	// Enable video callback function
	capSetCallbackOnFrame(hWndCap, frame_callback);

	// Set up video preview
	capPreviewRate(hWndCap, 1); // rate in ms
	capPreview(hWndCap, TRUE);
	ShowWindow(hWndCap, SW_SHOW);

	//Show main window
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	// Set timer to trigger snapshot
	//SetTimer(hWnd, 1, time_delay, NULL);

	// Message loop
	MSG msg;
	while(GetMessage(&msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	// Tidy up video capture stuff
	//KillTimer(hWnd, 1);
	capPreview(hWndCap, FALSE);
	capDriverDisconnect(hWndCap);
	if (hWndCap) DestroyWindow(hWndCap);

	return msg.wParam;
}
Advertisements
This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

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 )

Google+ photo

You are commenting using your Google+ 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 )

Connecting to %s