这才是我当年写出的一个比较烂的程序
?o>JX.Nl&7 3QD+&9{D Main2.bas
\#yKCA'; 6bE~m<B\` Attribute VB_Name = "SubMain"
[.
rULQl Option Explicit
X2PyFe tCVaRP8eC+ '采集文件与临时文件
K/;*.u`: Public Const TmpFile As String = "d:\30-0600.dat"
pXE'5IIN '已有数据:30-0600.dat /30日早6点进车与6:30出车头
>V,i7v*? a,/wqX Public fStatus As Long, hFile As Long, bytesRW As Long, lptrFile As Long
FD1Z}v!5IJ Public hBCFile As Long '记录采集参数的文件
jYxmU8 Public Const TmpBMP As String = "d:\1.bmp"
rGqT[~{t Public hTmpFile As Long
H\PY\O&cP VoGyjGt& 4WAs_~ '采集窗口参数常量
-(;<Q_'s{" Public Const FrameH As Long = 280&
=/Lwprj Public Const FrameW As Long = 768&
ES>iM)M Public Const pFrameSize As Long = FrameW * FrameH
n N_Ylw _u]S/X- '标志区范围,用于识别车辆
N!Q~?/!d Public Const PilarC As Integer = 260 '识别标志立柱中线坐标X
]lgI Q;r Public Const mkW As Integer = 28 '识别标志立柱宽度
4nz$Ja) Public Const mkH As Integer = 80 ''识别标志立柱高度(上白中黑下白)
lQ{o[axT Public Const mkY As Integer = 4 ''识别标志立柱Y坐标(40-79白, 80-119黑,120-159白)
N E/ _ Public Const mkX As Integer = PilarC - mkW / 2 '识别标志立柱X坐标
5ns.||%k '车缝检测位置常数
4b@Awtk Public Const sSize As Long = 32&
{0~xv@ U Public Const sPos As Long = 310&
YCBcyE}p Public Const sPosL As Long = 200&
K^yZfpa8 Public Const sPosR As Long = 500&
o3ZqPk]al '车缝检测框位置
9 aacW Public Slice(1 To sSize, 1 To FrameH) As Byte
&F 3'tf? Public SliceL(1 To sSize, 1 To FrameH) As Byte
B/^1uPTZ71 Public SliceR(1 To sSize, 1 To FrameH) As Byte
PF+SHT'4}# Public avSL As Integer, avSLR As Integer, avSLL As Integer
&Sr7?u`k c]x'}Kc TIIwq H+h. Public MKpilar(1 To mkW * mkH) As Byte '一维数组用于亮度对比度分析,比使用二维数组更便于VB编译优化
Kqn
{q4L '该数组用于亮度对比度调节、车辆通过识别与车皮间隔识别
CKu
f'h# Public BsLine(1 To 4 * FrameW) As Byte, bsAV As Integer '图像的前4行。用于确定标志区的亮度与对比度范围
8Buus Public PilarW As Long, PilarH As Long, PilarX As Long, PilarY As Long
.Bs~FIe^ Public LeftBK(1 To 1024, 0 To 1) As Byte, RightBK(1 To 1024, 0 To 1) As Byte
LP{@r ic '前后帧左右上角128列*8行像素块,根据平均值差绝对值判断进车方向
vNn$dc hgU#2`fS 0]u=GD% aG
x[?}= '一次连续采集的帧数
U#mrbW Public tFrames As Long
z]V%&f .B? J@, '在采集卡申请的缓存中,是按帧为单位的,每一帧包含奇偶场两场的数据
]nQC '而该卡的硬件设置是按场采集,只需要读第一场的数据即可。
0kiV-yc '所以要设置的缓存帧的大小是frameW*frameH*2,而一场的数据量为pFrameSize
a*N<gId -]-?>gkN5 Public pFRAME(1 To FrameW, 1 To FrameH) As Byte
wRCv?D`vV Public pBuffer(1 To FrameW * FrameH * 2) As Byte
xE"QX
N Public pWorkSpace(1 To FrameW * FrameH) As Long
*ak"}s Public Const pBufferSize As Long = FrameW * FrameH * 2
+8zCol?j Public pGray(0 To 255) As Long '整幅图像的灰度直方图
P.>5`^ T!ik"YZ@i Public hBoard As Long '采集卡标识
P-LdzVt(^ Public mBufferAddr As Long '缓存地址
<cUaIb;(4 Public BufferSize As Long '缓存大小(字节)
bpaS(nBy Public iCurrentCard As Long
|9;MP&68 Public CapStatus As Long
qy^sdqHl@ Public iFrames As Long
x 3C^ S~ Public currentBr As Byte, currentContr As Byte
LvcGh fnJ!~b*qo Public hMEM As Long, mStatus As Long
+wpQ$)\ Public Const hMemSize As Long = pFrameSize * 4
\)/dFo\l Public hMemWork As Long
"3H?_!A9 Public Const hMemWorkSize As Long = pFrameSize * 5
mW 4{*
9C"d7-- ][[\!og #^zUaPV 7r '串口接收轨道衡数据
{s
R|W:fS$ Public WeightFromCom As String
L>X39R~ Public bReceiveComplete As Boolean
hAvX{] b'mp$lt! k0>]7t$L Public Type GrayBMPHeader
q)F@f / Tag As Integer
sI% =G3o= FileLength As Long '文件大小
wF.S ,|
Reserve1 As Long
%AV[vr, DataOffset As Long '图像数据偏移量
MVYf-'\^ BMPHeaderSize As Long '文件头长
&`}8Jz=S 'length of the bitmap info header used to describe the bitmap colors, compression,…
;p] f5R^ 'the following sizes are possible:
WW.amv/[a '28h - windows 3.1x, 95, nt, …
Eq82?+9 '0ch - os/2 1.x
yu98d1 'f0h - os/2 2.x
UPr8Q^wm g-O}e4 ImageWidth As Long '图像宽(像素数)
'"4S3Fysm ImageHeight As Long '图像高(像素数)
QP={b+8 PlaneNumber As Integer '图像层数
-6yFE- X/ bpp As Integer 'bits per pixels '1 - monochrome bitmap
[+_0y[~,tB '4 - 16 color bitmap
vq_v;$9} '8 - 256 color bitmap
Dxx`<=&g
'16 - 16bit (high color) bitmap
+=JJ=F) '24 - 24bit (true color) bitmap
&"/IV$H '32 - 32bit (true color) bitmap
7zWr5U. Compression As Long '压缩方法 '0 - none (also identified by bi_rgb)
sR*.i?lN '1 - rle 8-bit / pixel (also identified by bi_rle4)
v0uA]6: '2 - rle 4-bit / pixel (also identified by bi_rle8)
R;3T yn+ '3 - bitfields (also identified by bi_bitfields)
q*pWx]Y IMAGESIZE As Long '图像数据字节数
/)LI1\o hResolution As Long '水平分辩率 像素数/米
=L F
9im vResolution As Long '垂直分辩率
d~za%2{ ColorsinBMP As Long '图中所用的颜色。对256色图像总为0x100
](tv`1A,Wd ImportantColors As Long
,2/y(JX}*! Pallate(0 To 255) As Long '图像每个值对应的实际显示颜色,项数对应PallateNumber所指调色板项数
Xt%>XP End Type
1^R:[L4R` 9i`sSi8
;qwNM~ lE 09 Y Public BMPHeader As GrayBMPHeader, BMP1 As GrayBMPHeader
O<}Kr
mUC~ Public sRECT As RECT
AriW&E 7TaHE
[KT1.5M[ Public conn As ADODB.Connection
OO /Pc Public rsTrain As ADODB.Recordset
I7@g,~s Public rsOperater As ADODB.Recordset
w}:&+B: Public rsGoods As ADODB.Recordset
\66j4?H# Public rsGood2 As ADODB.Recordset
meM61ue_2 Public rsSender As ADODB.Recordset
nLjc.Z\Bl Public rsReceover As ADODB.Recordset
m!H7;S-( Public rsTrainTMP As ADODB.Recordset
mvV5Xal 4.o[:5' !tckE\ h#N '打开采集卡
IHaNg
K2 '设置参数
}3xZ`vX[T '设置为实时单帧采集到缓存方式
yw{;Qm2\7 '由另一线程查询采集状态,如果完成采集,传送至用户数组分析或保存
iTpU4
Qsj 8Ug`2xS<_ f6O5k8n Sub Main()
Ljq!\D Dim i As Integer, status As Long
_=
d
X01 ,^d!K(xb InitBMPinfo
,f2tG+P '生成BMP文件头---该文件头是固定将pFRAME数组写成BMP文件
)?D w)s5 BMPHeader.Tag = &H4D42
W%.ou\GN^t BMPHeader.ImageWidth = FrameW
{ kF"<W BMPHeader.ImageHeight = FrameH
Btu=MUS BMPHeader.BMPHeaderSize = &H28
;~
,
<8 BMPHeader.PlaneNumber = 1
*LZ^0c: r BMPHeader.bpp = 8
o*}--d?S BMPHeader.Compression = 0
\8HLQly|@ BMPHeader.hResolution = &H1274 'Windows pBrush.exe的默认值,PhotoED.exe默值为0
%I>-_el BMPHeader.vResolution = &H1274
/N?vV
p BMPHeader.ColorsinBMP = 256
7Ew.6!s#n1 BMPHeader.ImportantColors = BMPHeader.ColorsinBMP
S`
v+rQjW BMPHeader.DataOffset = Len(BMPHeader)
d(> For i = 0 To 255
D/7hVwMw: BMPHeader.Pallate(i) = RGB(i, i, i)
g XThdNU4G Next i
tMQz'3,X BMPHeader.IMAGESIZE = FrameH * FrameW
Ei
&
Z BMPHeader.FileLength = Len(BMPHeader) + BMPHeader.IMAGESIZE
2ij/! $Afw]F$ KfkE'_F MoveMemory BMP1, BMPHeader, Len(BMPHeader)
hJIF!eoI %J%ZoptY: BMP1.ImageWidth = FrameW
r|!r!V8j BMP1.ImageHeight = FrameH * 2
wO&2S-;_K BMP1.IMAGESIZE = BMP1.ImageWidth * BMP1.ImageHeight
&:MfLDJ BMP1.FileLength = Len(BMP1) + BMP1.IMAGESIZE
f:6%DT~a&C Zv8I`/4? '确定标志位置,为pilarX, pilarY确定初始值
wEp*j+Mmce PilarW = mkW
b( qO fek PilarH = mkH '此两项为固定值
'<v_YxEn PilarX = GetSetting(App.EXEName, "Mark", "MarkX", mkX)
Pcox~U/j PilarY = GetSetting(App.EXEName, "Mark", "MarkY", mkY) '此两项需要在程序初始化时检查并进行调整
1;$8=j2 ujMics( fNllF,8} '连续采集记录文件
F')fi0= ' 建立一个缓冲区为页对齐方式的文件
cy+EJq I If Dir(TmpFile) <> "" Then
JRT,%;*, hFile = CreateFile(TmpFile, GENERIC_READ Or GENERIC_WRITE, _
(RtjD`e} 0&, 0&, OPEN_ALWAYS, FILE_FLAG_NO_BUFFERING, 0&)
^,;AM(E ' 在95/98中,如果打开文件时没有声明overlapped方式,在读定文件时就不能使用overlapped参数项
7\e96+j|f ' 而必须用setfilepointer函数调节与操作系统保留的文件指针。
eo~>|0A*V Else
sKU?"|G81G hFile = CreateFile(TmpFile, GENERIC_READ Or GENERIC_WRITE, _
0*-nVC1 0&, 0&, CREATE_ALWAYS, FILE_FLAG_NO_BUFFERING, 0&)
LsGu-Y5^ End If
7Rix=* If hFile = 0 Then
))z1T
8 MsgBox TmpFile & ": File Open Error", vbOKOnly
tUR9ti Exit Sub
K,o@~fj End If
e_{!8u.+ '采集参数记录文件
TA~YCj$ hBCFile = FreeFile()
28rC>*+z Open TmpFile + ".BC" For Binary Access Read Write As #hBCFile
Tl2e?El;4 H*&ZXAKv hMEM = VirtualAlloc(ByVal 0&, hMemSize, MEM_COMMIT, PAGE_READWRITE) ’分配系统内容
w6w'Jx If hMEM = 0 Then
w:~Y@b~D fStatus = GetLastError
lAcXi$pF MsgBox "内存分配错误: 错误代码 - " & Str(fStatus) & vbCrLf _
|'bRVqJ & "请向技术人员报告该错误代码。", vbOKOnly
4X^{aIlshk CloseHandle hFile
fL7u419= Exit Sub
MaX:oGF, End If
v7kR]HU[y (K>=!&tlp= hMemWork = VirtualAlloc(ByVal 0&, hMemWorkSize, MEM_COMMIT, PAGE_READWRITE)
-jJw wOm If hMemWork = 0 Then
S7
_^E fStatus = GetLastError
7vf?#^RlV MsgBox "内存分配错误: 错误代码 - " & Str(fStatus) & vbCrLf _
u^{6U(% & "请向技术人员报告该错误代码。", vbOKOnly
fvUD'
sx '释放已成功分配的内存
~BJ~]~0P` mStatus = VirtualFree(ByVal hMEM, hMemSize, MEM_DECOMMIT)
|loo^!I mStatus = VirtualFree(ByVal hMEM, 0&, MEM_RELEASE)
HvSYE[Zt| pHpHvSI CloseHandle hFile
AT6:&5_` Exit Sub
}[%d=NY End If
c'8a)j$$+ n$S`NNO{] ' Test writing
YEB@ p. 'WriteFile hFile, ByVal hMEM, ByVal 4096&, bytesRW, ByVal 0&
Q|+g= |%^ pPX ~pPIj2 '初始化采集卡参数
eJm7}\/6` iCurrentCard = -1
q%Fc?d9 hBoard = okOpenBoard(iCurrentCard)
XA%a7Xtni Debug.Print hBoard
^twJNm{99 If hBoard = 0 Then
y?1<7>L5~ ExitGrabber
`Rc7*2I)l End
<\If: End If
qK9\oB%s7 okGetBufferSize hBoard, mBufferAddr, BufferSize
uv,_?x\' If mBufferAddr = 0 Then
lv*fK
MsgBox "缓存不存在!"
@/m|T]'8 ExitGrabber
uDZ$'a End If
v-J9N(y" Debug.Print Hex(mBufferAddr), Hex(BufferSize)
+.RC{o, 4[eQ5$CB<u 1`X-
O> currentBr = 128: currentContr = 128
%%w/;o!c '设置视频输入参数
eyiGe1^C okSetVideoParam hBoard, VIDEO_SOURCECHAN, 1 'Video2
j+>#.22+ ' lParam=0,1.. Comp.Video; 0x100,101...to Y/C(S-Video), 0x200,0x201 to RGB Chan.Input
u
VZouw# okSetVideoParam hBoard, VIDEO_BRIGHTNESS, currentBr '亮度
(DW[#2\. okSetVideoParam hBoard, VIDEO_CONTRAST, currentContr '对比度 ---初始设置条件下如果图像亮度达不到基本要求则控制灯光
W"@FRWcd okSetVideoParam hBoard, VIDEO_RGBFORMAT, FORM_GRAY8 '8位灰度模式
W?B(Jsv okSetVideoParam hBoard, VIDEO_TVSTANDARD, 0 'PAL制式
22<T.c okSetVideoParam hBoard, VIDEO_SIGNALTYPE, &H10000 '逐行(低字)同步开槽(高字)
E9yBa=#*c okSetVideoParam hBoard, VIDEO_RECTSHIFT, 144 + &H2C0000 '有效区起始位置:高字Y偏移,低字X偏移 (144/44经验值)
ZPISclSA+
okSetVideoParam hBoard, VIDEO_AVAILRECTSIZE, FrameW + FrameH * 2 * &H10000 '有效区大小:低字X高字Y (768/576采集卡最大值)
$j\UD8Hj'- okSetVideoParam hBoard, VIDEO_FREQSEG, 0 ' 低频部分信号
TBz
Oz:k p`i_s(u '设置采集参数
h6Vm;{~ okSetCaptureParam hBoard, CAPTURE_INTERVAL, 0 '逐帧
$YM6}D@ okSetCaptureParam hBoard, CAPTURE_CLIPMODE, 2 '裁剪方式
g+-=/Ge okSetCaptureParam hBoard, CAPTURE_BUFRGBFORMAT, FORM_GRAY8 '8位灰度
y+PiH okSetCaptureParam hBoard, CAPTURE_HARDMIRROR, 0 '不作镜像变换
d5x>kO'[l okSetCaptureParam hBoard, CAPTURE_FRMRGBFORMAT, FORM_GRAY8 '帧存格式
c&o|I4|Y, okSetCaptureParam hBoard, CAPTURE_SAMPLEFIELD, 0 ' 逐场采集
D3>;X= 1 okSetCaptureParam hBoard, CAPTURE_HORZPIXELS, 944 '水平像素数 PAL制式固定值
:gNTQZR okSetCaptureParam hBoard, CAPTURE_VERTLINES, 625 '垂直线数
%!>~2=Q2* okSetCaptureParam hBoard, CAPTURE_SEQCAPWAIT, 0 '不等结束立即返回
4&+;n[ D 'okSetCaptureParam hBoard, CAPTURE_BUFBLOCKSIZE, FrameW + FrameH * 2 * &H10000
1;4]
HNI 'Buffer Block Size不用设置,而用okSetTargetRect函数进行动态调节
p
FkqDU (xJZeY)-b^ rU{E} okCloseBoard hBoard
0H6^2T< Sleep 50
jb~/>I^1 hBoard = okOpenBoard(iCurrentCard) '关闭后重新打开使新的设置值生效
~
}<!ON; mu1Lg s$; '设置数据传送方式
TyCMZsvM, 'okSetConvertParam hBoard, CONVERT_FIELDEXTEND, FIELD_COPYEXTEND '逐行并扩展行
nsCat($) '该设置对本程序无意义,因为程序直接用CopyMemory方法读缓存,而扩展行方式是在用采集卡内置函数读RECT过程中实现的。
&!kr&g#] c<8RRYs sRECT.Right = -1 '用于获得当前设置值
)/hb9+S iFrames = okSetTargetRect(hBoard, BUFFER, sRECT)
( _{\tgSm Debug.Print sRECT.Left, sRECT.Right, sRECT.Top, sRECT.Bottom
"1U:qr2-H Debug.Print okSetCaptureParam(hBoard, CAPTURE_BUFBLOCKSIZE, -1) 'FrameW + FrameH * &H10000
<Y(lRM{ sRECT.Left = 0
"^~>aVuXf sRECT.Top = 0
V0Z\e
_I sRECT.Right = sRECT.Left + FrameW
t1I` n(]n sRECT.Bottom = sRECT.Top + FrameH * 2
j3W)5ZX iFrames = okSetTargetRect(hBoard, BUFFER, sRECT)
/
xfg4 dUTF0U sRECT.Right = -1 '检查新设置值
'kD~tpZ iFrames = okSetTargetRect(hBoard, BUFFER, sRECT)
`Xbk2KD p Debug.Print sRECT.Left, sRECT.Right, sRECT.Top, sRECT.Bottom
cN{-&\
6L Debug.Print Hex(okSetCaptureParam(hBoard, CAPTURE_BUFBLOCKSIZE, -1))
(v\Cv)OS y'9
bs If TESTSignal = False Then
'~1uJ0H 'ExitGrabber
a09
]5>* End If
:V%XEN) vIoV(rc+ F_Q?0 Do0' JERWz~n} '设为实时采集状态
[,F5GW{x 'iFrames = okCaptureActive(hBoard, BUFFER, 0&)
:PrQ]ss@C5 _Vs\:tygs gGiLw5o, '单帧采集
E,#J\)'z
'okWaitSignalEvent hBoard, EVENT_FRAMEHEADER, -1
+U%U3tAvs 'iFrames = okCaptureSingle(hBoard, BUFFER, 0&)
LZCziW okCaptureTo hBoard, BUFFER, 0, 1 'single
U*Hw
t\ 'Do While okGetCaptureStatus(hBoard, False) <> 0
u,d@oF(= ' Sleep 20
}wJDHgt]-p 'Loop
-}Jf4k#G okGetCaptureStatus hBoard, True
f8Xe%"< MoveMemory pFRAME(1, 1), ByVal mBufferAddr, pFrameSize
r`Qzn" H '写入768*576测试图象
tsFwFB* ArrayToBMP TmpBMP
-'tgr6=|w" ml|[xM8 '打开数据库
QDRgVP Set conn = New ADODB.Connection
ZjE!?
'(ef conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
2#n4t2p "Persist Security Info=False;Data Source=" & "c:\train\train.mdb" & _
l"\W] 'T:r "; Mode=Read|Write"
9Fl}"p[>L. conn.Open
?5%|YsJP_ WrR97]7t frmRecord.Picture1.Picture = LoadPicture(TmpBMP)
?\QEK frmRecord.Visible = True
6[h3pb/m frmQuery.Visible = True
[>'P Load frmReceiveFromComm
8%UI<I, 0.^9)v*i '调试参数
dJh T}"x If InStr(UCase(Command()), "/CAPTURE") > 0 Then
7DU"QeLeb
SignalBox.Visible = True
cNW [i" End If
b ;Vy=f If InStr(UCase(Command()), "/COMM") > 0 Then
Om%9 x frmReceiveFromComm.Visible = True
[email protected]{s@ End If
sW":~=H axl!zu* End Sub
*S).@j\{W H-Uy~Ry*T Sub ExitGrabber()
By
t{3$ '关闭数据库
%C]K`=vI- '关闭采集卡
M~/%V NX mStatus = VirtualFree(ByVal hMEM, hMemSize, MEM_DECOMMIT)
2/9P&c-r