Pagi ini saya akan menjelaskan bagaimana cara membuat sebuah alat yang bisa digunakan untuk mengontrol device lain untuk melakukan apa yang kita inginkan menggunakan sebuah kamera, bisa kamera wireless maupu kamera nirkabel. Pada contoh kali ini sengaja saya akan mendemokan bagaimana cara mengendalikan led menyala menggunakan posisi kamera. memang alat dan bahan untuk membuat sistem ini tidaklah mudah, yaitu software Visual Studio 2010 dan OPENCV 2.3.1, hardwarenya yaitu kamera webcam, microcontroller, 4 buah led, RS232. jadi prinsip kerjanya sangat sederhana sekali, dari posisi object yang terdeteksi kamera kemudian object tersebut memberikan posisi X dan Y, posisi tersebut akan dikirimkan ke mikrokontroller melalui jalur serial RS232, sehingga mikrokontroller akan mengeksekusi perintah yang dikirim oleh komputer. berikut penjelasan skema dan programnya.
Tutorial cara konfigurasi OpenCV dengan Visual Studio bisa didownload di link berikut :
a. Minimum System
b. Rangkaian RS232
c. Program Bascom AVR
'=====================================================
'Programmer: Yanuar Mukhammad
'E-mail : Yanuarm@hotmail.com
'=====================================================
$regfile = "m16def.dat"
$crystal = 12000000
Dim Perintah As String * 1
Ddrb.0 = 1
Ddrb.1 = 1
Ddrb.2 = 1
Ddrc.5 = 1
Do
Perintah = Waitkey()
Select Case Perintah
Case "A" :
Portb.0 = 0
Portb.1 = 0
Portb.2 = 0
Portc.5 = 1
Case "B" :
Portb.0 = 0
Portb.1 = 0
Portb.2 = 1
Portc.5 = 0
Case "C" :
Portb.0 = 1
Portb.1 = 0
Portb.2 = 0
Portc.5 = 0
Case "D" :
Portb.0 = 0
Portb.1 = 1
Portb.2 = 0
Portc.5 = 0
End Select
Loop
'Programmer: Yanuar Mukhammad
'E-mail : Yanuarm@hotmail.com
'=====================================================
$regfile = "m16def.dat"
$crystal = 12000000
Dim Perintah As String * 1
Ddrb.0 = 1
Ddrb.1 = 1
Ddrb.2 = 1
Ddrc.5 = 1
Do
Perintah = Waitkey()
Select Case Perintah
Case "A" :
Portb.0 = 0
Portb.1 = 0
Portb.2 = 0
Portc.5 = 1
Case "B" :
Portb.0 = 0
Portb.1 = 0
Portb.2 = 1
Portc.5 = 0
Case "C" :
Portb.0 = 1
Portb.1 = 0
Portb.2 = 0
Portc.5 = 0
Case "D" :
Portb.0 = 0
Portb.1 = 1
Portb.2 = 0
Portc.5 = 0
End Select
Loop
d. Program Visual Studio
#include <iostream>
#include<opencv/cvaux.h>
#include<opencv/highgui.h>
#include<opencv/cxcore.h>
#include <sstream>
#include <string>
#include <opencv\cv.h>
#include<stdio.h>
#include<stdlib.h>
// Need to include this for serial port communication
#include <Windows.h>
////////////////////////////////////
using namespace cv;
//initial min and max HSV filter values.
//these will be changed using trackbars
int H_MIN = 0;
int H_MAX = 256;
int S_MIN = 0;
int S_MAX = 256;
int V_MIN = 0;
int V_MAX = 256;
//default capture width and height
const int FRAME_WIDTH = 640;
const int FRAME_HEIGHT = 480;
//max number of objects to be detected in frame
const int MAX_NUM_OBJECTS=100;
//minimum and maximum object area
const int MIN_OBJECT_AREA = 100*100;
const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH/1.5;
//names that will appear at the top of each window
//const string windowName = "Original Image";
//const string windowName1 = "HSV Image";
//const string windowName2 = "Thresholded Image";
//const string windowName3 = "After Morphological Operations";
const string trackbarWindowName = "Trackbars";
void on_trackbar( int, void* )
{//This function gets called whenever a
// trackbar position is changed
}
string intToString(int number){
std::stringstream ss;
ss << number;
return ss.str();
}
void createTrackbars(){
//create window for trackbars
namedWindow(trackbarWindowName,0);
//create memory to store trackbar name on window
char TrackbarName[50];
sprintf( TrackbarName, "H_MIN", H_MIN);
sprintf( TrackbarName, "H_MAX", H_MAX);
sprintf( TrackbarName, "S_MIN", S_MIN);
sprintf( TrackbarName, "S_MAX", S_MAX);
sprintf( TrackbarName, "V_MIN", V_MIN);
sprintf( TrackbarName, "V_MAX", V_MAX);
createTrackbar( "H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar );
createTrackbar( "H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar );
createTrackbar( "S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar );
createTrackbar( "S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar );
createTrackbar( "V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar );
createTrackbar( "V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar );
}
int main(int argc, char* argv[])
{
// Setup serial port connection and needed variables.
HANDLE hSerial = CreateFile(L"COM2", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hSerial !=INVALID_HANDLE_VALUE)
{
printf("Port opened! \n");
DCB dcbSerialParams;
GetCommState(hSerial,&dcbSerialParams);
dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.Parity = NOPARITY;
dcbSerialParams.StopBits = ONESTOPBIT;
SetCommState(hSerial, &dcbSerialParams);
}
else
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf("Serial port doesn't exist! \n");
}
printf("Error while setting up serial port! \n");
}
char outputChars[] = "c";
DWORD btsIO;
// Setup OpenCV variables and structures
CvSize size640x480 = cvSize(640, 480);
CvCapture* p_capWebcam;
IplImage* p_imgOriginal;
IplImage* p_imgProcessed;
IplImage* p_imgHSV;
CvMemStorage* p_strStorage;
CvSeq* p_seqCircles;
float* p_fltXYRadius;
// [0] => x position of detected object
// [1] => y position of detected object
int i;
char charCheckForEscKey;
p_capWebcam = cvCaptureFromCAM(1);
if(p_capWebcam == NULL) {
printf("error: capture is NULL \n");
getchar();
return(-1);
}
cvNamedWindow("Original", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Processed", CV_WINDOW_AUTOSIZE);
createTrackbars();
p_imgProcessed = cvCreateImage(size640x480,
IPL_DEPTH_8U,
1);
p_imgHSV = cvCreateImage(size640x480, IPL_DEPTH_8U, 3);
// Variables for Arduino Control
int servoPosition = 90;
int servoOrientation = 0;
int servoPosition1=90;
int servoOrientation1=0;
// Main program loop
while(1) {
p_imgOriginal = cvQueryFrame(p_capWebcam);
if(p_imgOriginal == NULL) {
printf("error: frame is NULL \n");
getchar();
break;
}
cvCvtColor(p_imgOriginal, p_imgHSV, CV_BGR2HSV);
cvInRangeS(p_imgHSV,
cvScalar(H_MIN, S_MIN, V_MIN),
cvScalar(H_MAX, S_MAX, V_MAX),
p_imgProcessed);
p_strStorage = cvCreateMemStorage(0);
cvSmooth(p_imgProcessed,
p_imgProcessed,
CV_GAUSSIAN,
9,
9);
p_seqCircles = cvHoughCircles(p_imgProcessed,
p_strStorage,
CV_HOUGH_GRADIENT,
2,
p_imgProcessed->height / 4,
100,
50,
10, //10
400);
if (p_seqCircles->total == 1)
{
p_fltXYRadius = (float*)cvGetSeqElem(p_seqCircles, 1);
printf("ball position x = %f, y = %f, r = %f \n", p_fltXYRadius[0],
p_fltXYRadius[1],
p_fltXYRadius[2]);
// atas
if (p_fltXYRadius[0] > 250 && p_fltXYRadius[0] < 300)
{
outputChars[0] = 'A';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
servoPosition+=1;
if (servoPosition > 180)
servoPosition = 180;
}
//kiri
if (p_fltXYRadius[0] < 80)
{
outputChars[0] = 'C';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
servoPosition-=1;
if (servoPosition < 0)
servoPosition = 0;
}
//kanan
if (p_fltXYRadius[0] > 500)
{
outputChars[0] = 'B';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
servoPosition1+=1;
if (servoPosition1 > 180)
servoPosition1 = 180;
}
//bawah
if (p_fltXYRadius[0] > 300 && p_fltXYRadius[0] < 400)
{
outputChars[0] = 'D';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
}
cvCircle(p_imgOriginal,
cvPoint(cvRound(p_fltXYRadius[0]), cvRound(p_fltXYRadius[1])),
3,
CV_RGB(0,255,0),
CV_FILLED);
cvCircle(p_imgOriginal,
cvPoint(cvRound(p_fltXYRadius[0]), cvRound(p_fltXYRadius[1])),
cvRound(p_fltXYRadius[2]),
CV_RGB(255,0,0),
3);
} // end for
cvShowImage("Original", p_imgOriginal);
cvShowImage("Processed", p_imgProcessed);
cvReleaseMemStorage(&p_strStorage);
charCheckForEscKey = cvWaitKey(10);
if(charCheckForEscKey == 27) break;
} // end while
cvReleaseCapture(&p_capWebcam);
cvDestroyWindow("Original");
cvDestroyWindow("Processed");
// This closes the Serial Port
CloseHandle(hSerial);
return(0);
}
#include<opencv/cvaux.h>
#include<opencv/highgui.h>
#include<opencv/cxcore.h>
#include <sstream>
#include <string>
#include <opencv\cv.h>
#include<stdio.h>
#include<stdlib.h>
// Need to include this for serial port communication
#include <Windows.h>
////////////////////////////////////
using namespace cv;
//initial min and max HSV filter values.
//these will be changed using trackbars
int H_MIN = 0;
int H_MAX = 256;
int S_MIN = 0;
int S_MAX = 256;
int V_MIN = 0;
int V_MAX = 256;
//default capture width and height
const int FRAME_WIDTH = 640;
const int FRAME_HEIGHT = 480;
//max number of objects to be detected in frame
const int MAX_NUM_OBJECTS=100;
//minimum and maximum object area
const int MIN_OBJECT_AREA = 100*100;
const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH/1.5;
//names that will appear at the top of each window
//const string windowName = "Original Image";
//const string windowName1 = "HSV Image";
//const string windowName2 = "Thresholded Image";
//const string windowName3 = "After Morphological Operations";
const string trackbarWindowName = "Trackbars";
void on_trackbar( int, void* )
{//This function gets called whenever a
// trackbar position is changed
}
string intToString(int number){
std::stringstream ss;
ss << number;
return ss.str();
}
void createTrackbars(){
//create window for trackbars
namedWindow(trackbarWindowName,0);
//create memory to store trackbar name on window
char TrackbarName[50];
sprintf( TrackbarName, "H_MIN", H_MIN);
sprintf( TrackbarName, "H_MAX", H_MAX);
sprintf( TrackbarName, "S_MIN", S_MIN);
sprintf( TrackbarName, "S_MAX", S_MAX);
sprintf( TrackbarName, "V_MIN", V_MIN);
sprintf( TrackbarName, "V_MAX", V_MAX);
createTrackbar( "H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar );
createTrackbar( "H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar );
createTrackbar( "S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar );
createTrackbar( "S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar );
createTrackbar( "V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar );
createTrackbar( "V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar );
}
int main(int argc, char* argv[])
{
// Setup serial port connection and needed variables.
HANDLE hSerial = CreateFile(L"COM2", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hSerial !=INVALID_HANDLE_VALUE)
{
printf("Port opened! \n");
DCB dcbSerialParams;
GetCommState(hSerial,&dcbSerialParams);
dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.Parity = NOPARITY;
dcbSerialParams.StopBits = ONESTOPBIT;
SetCommState(hSerial, &dcbSerialParams);
}
else
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf("Serial port doesn't exist! \n");
}
printf("Error while setting up serial port! \n");
}
char outputChars[] = "c";
DWORD btsIO;
// Setup OpenCV variables and structures
CvSize size640x480 = cvSize(640, 480);
CvCapture* p_capWebcam;
IplImage* p_imgOriginal;
IplImage* p_imgProcessed;
IplImage* p_imgHSV;
CvMemStorage* p_strStorage;
CvSeq* p_seqCircles;
float* p_fltXYRadius;
// [0] => x position of detected object
// [1] => y position of detected object
int i;
char charCheckForEscKey;
p_capWebcam = cvCaptureFromCAM(1);
if(p_capWebcam == NULL) {
printf("error: capture is NULL \n");
getchar();
return(-1);
}
cvNamedWindow("Original", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Processed", CV_WINDOW_AUTOSIZE);
createTrackbars();
p_imgProcessed = cvCreateImage(size640x480,
IPL_DEPTH_8U,
1);
p_imgHSV = cvCreateImage(size640x480, IPL_DEPTH_8U, 3);
// Variables for Arduino Control
int servoPosition = 90;
int servoOrientation = 0;
int servoPosition1=90;
int servoOrientation1=0;
// Main program loop
while(1) {
p_imgOriginal = cvQueryFrame(p_capWebcam);
if(p_imgOriginal == NULL) {
printf("error: frame is NULL \n");
getchar();
break;
}
cvCvtColor(p_imgOriginal, p_imgHSV, CV_BGR2HSV);
cvInRangeS(p_imgHSV,
cvScalar(H_MIN, S_MIN, V_MIN),
cvScalar(H_MAX, S_MAX, V_MAX),
p_imgProcessed);
p_strStorage = cvCreateMemStorage(0);
cvSmooth(p_imgProcessed,
p_imgProcessed,
CV_GAUSSIAN,
9,
9);
p_seqCircles = cvHoughCircles(p_imgProcessed,
p_strStorage,
CV_HOUGH_GRADIENT,
2,
p_imgProcessed->height / 4,
100,
50,
10, //10
400);
if (p_seqCircles->total == 1)
{
p_fltXYRadius = (float*)cvGetSeqElem(p_seqCircles, 1);
printf("ball position x = %f, y = %f, r = %f \n", p_fltXYRadius[0],
p_fltXYRadius[1],
p_fltXYRadius[2]);
// atas
if (p_fltXYRadius[0] > 250 && p_fltXYRadius[0] < 300)
{
outputChars[0] = 'A';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
servoPosition+=1;
if (servoPosition > 180)
servoPosition = 180;
}
//kiri
if (p_fltXYRadius[0] < 80)
{
outputChars[0] = 'C';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
servoPosition-=1;
if (servoPosition < 0)
servoPosition = 0;
}
//kanan
if (p_fltXYRadius[0] > 500)
{
outputChars[0] = 'B';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
servoPosition1+=1;
if (servoPosition1 > 180)
servoPosition1 = 180;
}
//bawah
if (p_fltXYRadius[0] > 300 && p_fltXYRadius[0] < 400)
{
outputChars[0] = 'D';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
}
cvCircle(p_imgOriginal,
cvPoint(cvRound(p_fltXYRadius[0]), cvRound(p_fltXYRadius[1])),
3,
CV_RGB(0,255,0),
CV_FILLED);
cvCircle(p_imgOriginal,
cvPoint(cvRound(p_fltXYRadius[0]), cvRound(p_fltXYRadius[1])),
cvRound(p_fltXYRadius[2]),
CV_RGB(255,0,0),
3);
} // end for
cvShowImage("Original", p_imgOriginal);
cvShowImage("Processed", p_imgProcessed);
cvReleaseMemStorage(&p_strStorage);
charCheckForEscKey = cvWaitKey(10);
if(charCheckForEscKey == 27) break;
} // end while
cvReleaseCapture(&p_capWebcam);
cvDestroyWindow("Original");
cvDestroyWindow("Processed");
// This closes the Serial Port
CloseHandle(hSerial);
return(0);
}
e. VIDEO HASILNYA
Jika saat menjalankan program terdapat error "tbb.dll is missing" maka lakukanlah langkah berikut.
1. Copy file "tbb.dll" di "C:\opencv\build\common\tbb\bin\ia32\vc10"
2. Kemudian paste di "C:\Users\yanuar\Documents\Visual Studio 2010\Projects"
3. Selamat berkarya
1. Copy file "tbb.dll" di "C:\opencv\build\common\tbb\bin\ia32\vc10"
2. Kemudian paste di "C:\Users\yanuar\Documents\Visual Studio 2010\Projects"
3. Selamat berkarya