<textarea class="cpp" rows="10" cols="60" name="code">// 載第三張圖 -----------------------------------------------------------
Form1->Image3->Picture->LoadFromFile("Picture\\pic3.bmp");
stop = 0; //Timer的控制變數
//時間控制 -----------------------------------------------------------------
HANDLE hEvent = CreateEvent(NULL, false, false, NULL);
int TimerID = timeSetEvent(33, 0, (LPTIMECALLBACK)hEvent, 0, TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);
//間距 //精確度
do
{
//算程式執行時間(跟上述時間控制為分開的)----------------------------------
QueryPerformanceFrequency(&L);
Freq = (int)(L.QuadPart/1000);
QueryPerformanceCounter(&StartTime);
//時間控制----------------------------------------------------------------
WaitForSingleObject(hEvent, INFINITE); //學寬達
Application->ProcessMessages(); //Yann:這樣才不會把 CPU Hold 住
// 以下放置主要程式碼 //------------------------------------------------
LTimer ; //用來辨別現在是單數還是雙數張
if (LTimer==20)
{
LTimer=2; //將Timer歸零,以免到最後數字太大,變成系統負擔
}
if (LTimer%2==1)
{
// 抓第一張圖 & 載圖 -------------------------------------------------
capFileSaveDIB(ghCapWnd1,"Picture\\pic1.bmp");
Form1->Image1->Picture->LoadFromFile("Picture\\pic1.bmp");
}
else if (LTimer%2==0)
{
// 抓第二張圖 & 載圖 -------------------------------------------------
capFileSaveDIB(ghCapWnd1,"Picture\\pic2.bmp");
Form1->Image2->Picture->LoadFromFile("Picture\\pic2.bmp");
}
/*
// 載第三張圖 -----------------------------------------------------------
Form1->Image3->Picture->LoadFromFile("Picture\\pic3.bmp");
*/
//當大於第二張圖時開始動作------------------------------------------------
if (LTimer>=2)
{
// 預留指標空間放圖----------------------------------------------------
Graphics::TBitmap *Bitmap1=new Graphics::TBitmap;
Graphics::TBitmap *Bitmap2=new Graphics::TBitmap;
Graphics::TBitmap *Bitmap3=new Graphics::TBitmap;
Byte *ptr1,*ptr2,*ptr3,*ptr4;
Bitmap1= Image1->Picture->Bitmap;
Bitmap2= Image2->Picture->Bitmap;
Bitmap3= Image3->Picture->Bitmap;
//將要量化用的值歸零,以利下面的量化-----------------------------------
/*
max1=0;
max2=0;
min1=0;
min2=0;
*/
// 對指定區域做影像處理------------------------------------------------
for ( y = Ymin; y < Ymax; y )
{
ptr1 = (Byte *)Bitmap1->ScanLine[y];
ptr2 = (Byte *)Bitmap2->ScanLine[y];
for ( x = Xmin; x < Xmax; x )
{
b1=ptr1[x*3];
g1=ptr1[x*3 1];
r1=ptr1[x*3 2];
b2=ptr2[x*3];
g2=ptr2[x*3 1];
r2=ptr2[x*3 2];
// 影像灰階化之公式為:『 Gray = 0.299*R 0.587*G 0.114*B 』
show1[x][y]=(0.299*r1 0.587*g1 0.114*b1);
show2[x][y]=(0.299*r2 0.587*g2 0.114*b2);
//影像相減,這邊為減背景影像-------------------------------------
show1[x][y]=show1[x][y]-show[x][y];
show2[x][y]=show2[x][y]-show[x][y];
//找量化用的最大最小值-------------------------------------------
if(show1[x][y]>=max1)
{
max1=show1[x][y];
}
if (show1[x][y]=max2)
{
max2=show2[x][y];
}
if (show2[x][y]ScanLine[y];
ptr3 = (Byte *)Bitmap3->ScanLine[y];
for ( x = Xmin; x < Xmax; x )
{
//將值量化在 0 ~ 255 間------------------------------------------
show1[x][y]=255*(show1[x][y]-min1)/(max1-min1);
show2[x][y]=255*(show2[x][y]-min2)/(max2-min2);
// 影像二值化閥值,用於過濾雜訊,將圖轉成白與黑------------------
if (show1[x][y] < TwoTh) //做第一張圖
{
show1[x][y]=0;
num1 = num1 1 ; // 以下三行待會算形心會用到,合併寫這而已~
totalx1 = totalx1 x;
totaly1 = totaly1 y;
}
else
{
show1[x][y]=255;
}
if (show2[x][y] < TwoTh) //做第二張圖
{
show2[x][y]=0;
num2 = num2 1 ; // 以下三行待會算形心會用到,合併寫這而已~
totalx2 = totalx2 x;
totaly2 = totaly2 y;
}
else
{
show2[x][y]=255;
}
// 影像相減------------------------------------------------------
if (LTimer%2==1) //當取至單數張時,由單減雙
{
show3=abs(show1[x][y]-show2[x][y]);
}
else if (LTimer%2==0) //當取至雙數張時,由雙減單
{
show3=abs(show2[x][y]-show1[x][y]);
}
// 影像相減閥值,用於過濾雜訊,找出運動物體----------------------
if (show3>SubTh)
{
show3=0;
}
else
{
show3=255;
}
// 將指標存回圖--------------------------------------------------
ptr2[x*3]=(Byte)show2[x][y]; // 輸入影像的 B 值
ptr2[x*3 1]=(Byte)show2[x][y]; // 輸入影像的 G 值
ptr2[x*3 2]=(Byte)show2[x][y]; // 輸入影像的 R 值
ptr3[x*3]=(Byte)show3;
ptr3[x*3 1]=(Byte)show3;
ptr3[x*3 2]=(Byte)show3;
}
}
// 將符號轉成可視圖
Form1->Image2->Picture->Assign(Bitmap2); // 利用 Assign 指令將影像資料還原成圖片。
Form1->Image2->Picture->SaveToFile("Picture\\pic2.bmp"); // 儲存圖檔。
Form1->Image3->Picture->Assign(Bitmap3); // 利用 Assign 指令將影像資料還原成圖片。
Form1->Image3->Picture->SaveToFile("Picture\\pic3.bmp"); // 儲存圖檔。
//避免在靜止狀態下~在算形心時會除以零發生錯誤--------------------------
if (num1==0)
{
num1 ;
}
if (num2==0)
{
num2 ;
}
//判斷球盤有無在計算範圍內---------------------------------------------
if (num1>=20 & num2>=20) //當畫面有球盤時,即進行下列運算
{
// 算形心位置並顯示出來---------------------------------------------
Chx1 = totalx1/num1;
Chy1 = totaly1/num1;
Chx2 = totalx2/num2;
Chy2 = totaly2/num2;
if (LTimer%2==1) //當取至單數張時,由雙減單
{
dx=Chx1-Chx2; //由原點減新點來得知方位,待會算角度用
dy=Chy1-Chy2;
}
else if (LTimer%2==0) //當取至雙數張時,由單減雙
{
dx=Chx2-Chx1;
dy=Chy2-Chy1;
}
if(abs(dx)<2) //用來降低敏感度,讓形心位置可以穩定
{ // 2 為自行設定值,愈高愈穩,但也愈遲鈍
Chx1=Chx2;
}
if(abs(dy)<2)
{
Chy1=Chy2;
}
if (LTimer%2==1) //當取至單數張時所顯示形心最新位置
{
Label8->Caption = "(" IntToStr(Chx1) "," IntToStr(Chy1) ")" ;
Chx=Chx1;
Chy=Chy1;
}
if (LTimer%2==0) //當取至雙數張時所顯示形心最新位置
{
Label8->Caption = "(" IntToStr(Chx2) "," IntToStr(Chy2) ")" ;
Chx=Chx2;
Chy=Chy2;
}
// 算速度並顯示出來-------------------------------------------------
pc=100.5/157; //47/71 為 1 像素換算多少公分 pixel --> cm
v=hypot(dx,dy)*pc/dtime; // 速度
vx= fabs(Chx2-Chx1)*pc/dtime; // x 速度分量
vy= fabs(Chy2-Chy1)*pc/dtime; // y 速度分量
if(Chx2==Chx1 & Chy2==Chy1)
{
Label10->Caption = " 0 cm/s";
}
else //方便我們看現在的數據用
{
Label10->Caption = FloatToStrF(v , ffFixed, 9, 2) " cm/s";
}
//算角度------------------------------------------------------------
if (dx!=0 & dy!=0) //《注意》像素值以向下(Y軸)向右(X軸)為正
{
dxy=hypot(dx,dy); //dx dy平方開根號
Th=asin(fabs(dy)/dxy)*180/pi;
if(dx>0 & dy<0) //第一象限
{
dsign=1; // 1 代表 " "
Label19->Caption = FloatToStrF(Th , ffFixed, 9, 2); //四捨五入至小數第二位
}
else if(dx<0 & dy<0) //第二象限
{
dsign=0; // 0 代表 "-"
Th=180-Th;
Label19->Caption = FloatToStrF(Th , ffFixed, 9, 2); //四捨五入至小數第二位
}
else if(dx<0 & dy>0) //第三象限
{
Th=180 Th;
Label19->Caption = FloatToStrF(Th , ffFixed, 9, 2); //四捨五入至小數第二位
}
else if(dx>0 & dy>0) //第四象限
{
Th=360-Th;
Label19->Caption = FloatToStrF(Th , ffFixed, 9, 2); //四捨五入至小數第二位
}
}
else
{
//Label19->Caption = "0" ;
}
//擷取第一筆資料----------------------------------------------------
if ((Chx<=Soutx) && ((Chx1>Soutx) || (Chx2>Soutx))) // 取己方資料
{
doutnum ;
/*
outdata[doutnum][0]= vx;
outdata[doutnum][1]= vy;
outdata[doutnum][2]= Chx;
outdata[doutnum][3]= Chy;
outdata[doutnum][4]= Th;
*/
if((doutnum-1)!=dinnum) //用來判斷取值是否有成功
{
doutnum--;
}
else
{
outtemp[0]= vx;
outtemp[1]= vy;
outtemp[2]= Chx;
outtemp[3]= Chy;
outtemp[4]= Th;
}
}
if ((Chx<=Sinx) && ((Chx1>Sinx) || (Chx2>Sinx))) // 取對方資料
{
dinnum ;
/*
indata[dinnum][0]= vx;
indata[dinnum][1]= vy;
indata[dinnum][2]= Chx;
indata[dinnum][3]= Chy;
indata[dinnum][4]= Th;
*/
if(doutnum!=dinnum) //用來判斷取值是否有成功
{
dinnum--;
}
else
{
intemp[0]= vx;
intemp[1]= vy;
intemp[2]= Chx;
intemp[3]= Chy;
intemp[4]= Th;
if(doutnum==dinnum) //當兩邊取值數相同時,才進行取值
{
//存成 txt 檔,供 RBFN 訓練
outdata=fopen("data\\out.txt", "a");
fprintf(outdata,"%f %f %f %f %f",outtemp[0],outtemp[1],outtemp[2],outtemp[3],outtemp[4]);
fprintf(outdata,"\n"); // 換行
fclose(outdata);
//存成 txt 檔,供 RBFN 訓練
indata=fopen("data\\in.txt", "a");
fprintf(indata,"%f %f %f %f %f",intemp[0],intemp[1],intemp[2],intemp[3],intemp[4]);
fprintf(indata,"\n"); // 換行
fclose(indata);
}
}
}
Label26->Caption=dinnum; //看結果各取了幾筆
Label27->Caption=doutnum;
}
else //當畫面沒有球盤時,將一切歸零
{
/*
Chx1=0;
Chx2=0;
Chy1=0;
Chy2=0;
v=0;
vx=0;
vy=0;
Th=0;
Label8->Caption = "(" IntToStr(Chx2) "," IntToStr(Chy2) ")" ;
Label10->Caption = FloatToStrF(v , ffFixed, 9, 2) " cm/s";
Label19->Caption = FloatToStrF(Th , ffFixed, 9, 2); //四捨五入至小數第二位
*/
Label8->Caption = "(0,0)" ;
Label10->Caption = " 0 cm/s";
Label19->Caption = "0"; //四捨五入至小數第二位
}
//畫線區分要計算的範圍-------------------------------------------------
Image3->Canvas->Pen->Color=clRed; //紅線為取值範圍
Image3->Canvas->MoveTo(Sinx,0);
Image3->Canvas->LineTo(Sinx,240);
Image3->Canvas->MoveTo(Soutx,0);
Image3->Canvas->LineTo(Soutx,240);
Image3->Canvas->Pen->Color=clGreen; //綠線為計算範圍
Image3->Canvas->MoveTo(Xmin,0);
Image3->Canvas->LineTo(Xmin,240);
Image3->Canvas->MoveTo(Xmax,0);
Image3->Canvas->LineTo(Xmax,240);
//算總行數-------------------------------------------------------------
TStringList *slData1 = new TStringList;
slData1->LoadFromFile("data//in.txt");
Label28->Caption = IntToStr(slData1->Count);
TStringList *slData2 = new TStringList;
slData2->LoadFromFile("data//out.txt");
Label33->Caption = IntToStr(slData2->Count);
aaa ;
Label35->Caption = aaa;
}
//以上為程式執行所需時間-----------------------------------------------
QueryPerformanceCounter(&L);
dtime=(L.QuadPart - StartTime.QuadPart)/(1000.*Freq); //算一張圖所花費時間
Label34->Caption = FloatToStr(dtime) " 秒";
//---以上放置主程式----------------------------------------------------------
} while (stop == 0);
timeKillEvent(TimerID);
CloseHandle(hEvent); //以上為時間控制----------------------------------
</textarea><br />
以上為我主要的程式碼~
經測試~
當有
capFileSaveDIB(ghCapWnd1,"Picture\\pic1.bmp");
Form1->Image1->Picture->LoadFromFile("Picture\\pic1.bmp");
這抓圖指令時
約縮減 5 fps
當有影像相減
約縮減10 fps
而上述關於硬體部份,已解決~剩此軟體部分~
一直想不出更快的方法
謝謝你的耐心回覆!