整体思路
体积计算:
利用由三个一字激光器包裹在物体上形成了一个光圈,将物体放在由51单片机控制的升降台上,在光圈的上方垂直放置CCD。通过升降台的上下垂直移动,光圈的大小也在随之变化,用CCD来抓拍其变化,之后传至电脑通过Matlab对接收到的图像进行处理,根据升降台的速度和对处理后图片光圈内所包围的面积进行体积分,得到其体积。
三维还原:
相机接收到的每张图像为此物体在此高度的切层图像,将每一层的切层图像保存到一个三维数组中,通过Matlab中的函数可以将物体在电脑上还原出来。
在线式测量及还原:
若要实现在线式测量及三维还原,则需将升降台升降、相机抓拍图像,上位机处理图像并计算测量通过软件设计得可以实时进行测量。其实现思路为:通过USB2.0接口将单片机和摄像机与上位机连接起来实时通信,并且利用Matlab的GUI界面进行人机交互。
一、下位机部分
1、实现功能:
——通过51单片机控制步进电机的转速;
——51单片机与上位机的实时通信;
2、整体框图:
3、功能代码:
#include<reg52.h>
#include<intrins.h>
#define k P1
typedef unsigned char u8;
typedef unsigned int u16;
unsigned char T0_NUM;
unsigned char code a[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};// 显示段码值0~9
unsigned char MotorTab[11] = {100,50,40,25,20,10,8,5,4,2,1};//改变频率
signed char g_MotorNum = 0;
unsigned char disp[4]={0};
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit beep=P1^5;
sbit FX = P2^7; // 方向
sbit CLK = P2^6; // 脉冲
u8 shu[4];
u16 num=0,aa=0;
void InitUART();
void initUART(void)//串口通信初始化
{
SCON =0x50;
TMOD |= 0x20;
PCON=0X80;
TH1 = 0xF3;
TL1 = 0xF3;
TR1 = 1;
ES = 1;
EA = 1;
}
void T0_Init()//中断初始化(控制频率信号)
{
TMOD |= 0x01;
TH0 = 0xff; // 0.1ms
TL0 = 0x9c;
IT0=1;//下降沿触发
EX0=1;//打开中断0允许
EA = 1;
ET0 = 1;
}
void delay(u16 i)//延时函数
{
while(--i);
}
void delay1s(void) //延时1s
{
unsigned char a,b,c;
for(c=46;c>0;c--)
for(b=152;b>0;b--)
for(a=70;a>0;a--);
_nop_(); //if Keil,require use intrins.h
}
void datapros() //数码管显示
{
shu[0]=a[aa/1000];
shu[1]=a[aa%1000/100]; //bai
shu[2]=a[aa%1000%100/10]; //shi
shu[3]=a[aa%1000%100%10];
if(shu[0]==0x3f)
{
shu[0]=a[10];
if((shu[0]==0x00)&&(shu[1]==0x3f))
{
shu[1]=a[10];
if((shu[0]==0x00)&&(shu[1]==0x00)&&(shu[2]==0x3f))
{
shu[2]=a[10];
}
}
}
}
void DidDisplay() //138译码器
{
u8 i;
for(i=0;i<4;i++)
{
switch(i)
{
case 0:
LSA=0;LSB=0;LSC=0;break;
case 1:
LSA=1;LSB=0;LSC=0;break;
case 2:
LSA=0;LSB=1;LSC=0;break;
case 3:
LSA=1;LSB=1;LSC=0;break;
}
P0=shu[3-i];
delay(100);
P0=0x00;
}
}
void main (void)//主函数
{
beep=0;
FX = 0;
InitUART();
T0_Init();
while(1)
{
datapros();
DidDisplay();
}
}
void SendByte(u8 i)//向上位机发送一个字节
{
SBUF=i;
while(TI==0);
TI=0;
}
void UART_SER (void) interrupt 4 //串口中断
{
TI=0;
RI=0;
if(SBUF=='H')
{
SendByte('O');
SendByte('K');
aa=1010;
}
else if(SBUF=='1')
{
g_MotorNum=0;
TR0=1;
FX = 1;
aa=50;
}
else if(SBUF=='2')
{
g_MotorNum=1;
TR0=1;
FX = 1;
aa=100;
}
else if(SBUF=='3')
{
g_MotorNum=2;
TR0=1;
FX = 1;
aa=125;
}
else if(SBUF=='4')
{
g_MotorNum=3;
TR0=1;
FX = 1;
aa=200;
}
else if(SBUF=='5')
{
g_MotorNum=4;
TR0=1;
FX = 1;
aa=250;
}
else if(SBUF=='6')
{
g_MotorNum=5;
TR0=1;
FX = 1;
aa=500;
}
else if(SBUF=='7')
{
g_MotorNum=6;
TR0=1;
FX = 1;
aa=625;
}
else if(SBUF=='8')
{
g_MotorNum=7;
TR0=1;
FX = 1;
aa=1000;
}
else if(SBUF=='9')
{
g_MotorNum=8;
TR0=1;
FX = 1;
aa=1250;
}
else if(SBUF=='a')
{
g_MotorNum=9;
TR0=1;
FX = 1;
aa=2500;
}
else if(SBUF=='b')
{
g_MotorNum=10;
TR0=1;
FX = 1;
aa=5000;
}
else if(SBUF=='D') /控制电机移动一点距离然后停止 250hz
{
g_MotorNum=4;
TR0=1;
FX = 1;
delay1s();
TR0=0;
aa=1110;
}
else if(SBUF=='S') /控制电机停止
{
TR0=0;
aa=1111;
}
}
void T0_time() interrupt 1 //控制频率
{
TH0 = 0xff;
TL0 = 0x9c;
T0_NUM++;
if(T0_NUM >= MotorTab[g_MotorNum])
{
T0_NUM = 0;
CLK=CLK^0x01;
}
}
二、上位机调用相机部分
1、实现功能:
——通过Matlab工具箱中函数对相机进行调用;
——相机对光圈进行等间距拍摄;
2、函数介绍:
- 查询USB2.0Camera的具体参数
>> info=imaqhwinfo
info =
InstalledAdaptors: {'winvideo'} %%%可以看到PC上安装的一个适配器
MATLABVersion: '9.0 (R2016a)'
ToolboxName: 'Image Acqui…'
ToolboxVersion: '5.0 (R2016a)'
让我们来看其具体的参数
>> info=imaqhwinfo('winvideo')
info =
AdaptorDllName: 'C:\MATLAB\S…'%%%适配器dll文件绝对路径
AdaptorDllVersion: '5.0 (R2016a)'%%%适配器dll文件版本
AdaptorName: 'winvideo'%%%适配器名称
DeviceIDs: {[1]}%%%设备ID号
DeviceInfo: [1x1 struct]%%%设备信息,获取图像的一些参数,比较重要
以下为设备的信息参数
>> info.DeviceInfo
ans =
1x2 struct array with fields:
DefaultFormat %%%图像默认格式
DeviceFileSupported
DeviceName %%%设备名称
DeviceID %%%设备号
VideoInputConstructor
VideoDeviceConstructor
SupportedFormats %%%图像支持格式
>> info.DeviceInfo. DefaultFormat
ans =
YUY2_160x120 %%%图像默认格式
>> info.DeviceInfo. SupportedFormats
ans = %%%图像支持格式
1 至 2 列
'YUY2_160x120' 'YUY2_176x144'
3 至 4 列
'YUY2_320x240' 'YUY2_352x288'
5 列
'YUY2_640x480'
- 创建视频输入对象
>> obj=videoinput('winvideo',1,'YUY2_640x480')
%%%%%%%%%videoinput(‘设备名称’,设备号,‘视频采集格式’)
Summary of Video Input Object Using 'USB Camera'.
Acquisition Source(s): input1 is available.
Acquisition Parameters: 'input1' is the current selected source.
10 frames per trigger using the selected source.
'YUY2_640x480' video data to be logged upon START.
Grabbing first of every 1 frame(s).
Log data to 'memory' on trigger.
Trigger Parameters: 1 'immediate' trigger(s) on START.
Status: Waiting for START.
0 frames acquired since starting.
0 frames available for GETDATA.
- 打开视频预览窗口
>>t1=get(obj,'VideoResolution');
>>t2=get(obj,'NumberOfBands');
>>figure();
>>t=image(zeros(t1(2),t1(1),t2));
>>preview(obj,t)%%t为视频预览窗口对应的句柄,该参数可以空缺
- 图像的捕捉显示与保存
>> frame=getsnapshot(obj)%%%获取图像函数
>>imshow(frame)
>>imwrite(frame,'snap.bmp','bmp')%%%%%写入数据函数
以上便是上位机调用相机部分
tips:“>>为Matlab界面中输入部分”