Excel VBA在处理批量数据时具有便捷高效的特点,也可以基于数据绘图,但是在处理图片的能力却略显不足,而Image J[1]这一开源的图像处理软件在图像处理方面的功能则非常强大,同时由于Image J可以运扩展的脚本(macro),因此在实际应用中可以结合VBA和Image J来处理需要导入excel表格的图片。
如下图所示,在一个文件夹中有多张(以3张举例)Raw格式的图片,现在需要将它们转换成Bmp格式,同时对Bmp格式图片进行增加对比度处理,并把这两种类型的图片读入Excel表格中按组放置,左边是转换后的Bmp格式图片,右边是对比度处理后的Bmp图片。
Image J软件界面,其中plugins >> Macros可以运行扩展的脚本。
本案例的策略是利用VBA遍历获取每一个图片文件的名称,然后将处理图片的代码写入到Image J可以运行的Ijm格式文件中,再用Image J运行脚本逐张处理图片,最后再用VBA把图片导入到excel指定位置上。
具体实现代码如下:
Sub Find_Lot_List()
BookFileName = ThisWorkbook.Name
Dim i, Total_TXTfiles As Integer
Dim path, TxtFileName2nd As String
Dim Total_lot_Count As Integer
Dim ppFileName As String
Set shLotList = Workbooks(BookFileName).Worksheets("lot_list")
path = shLotList.Cells(1, 2)
shLotList.Select
shLotList.Rows("2:65534").Select
Selection.ClearContents
Total_TXTfiles = 0
CheckFileName = "*.raw"
TxtFileName2nd = Dir(IIf(Right(path, 1) <> "\", path & "\", path) & CheckFileName)
Do While TxtFileName2nd <> ""
shLotList.Cells(Total_TXTfiles + 2, 1) = TxtFileName2nd 'IIf(Right(path, 1) <> "\", path & "\", path) & TxtFileName2nd
shLotList.Cells(Total_TXTfiles + 2, 2) = FileDateTime(path & "\" & TxtFileName2nd)
Total_TXTfiles = Total_TXTfiles + 1
TxtFileName2nd = Dir()
Loop
Total_lot_Count = Total_TXTfiles
'将B列数据(测试时间)按照顺序排列,可以用来映射图片与数据,保证图片与数据一一对应
shLotList.Sort.SortFields.Add Key:=Range("B1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With shLotList.Sort
.SetRange Range("A2:B10000")
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
ppFileName = IIf(Right(path, 1) <> "\", path & "\", path) & "Raw to" & " " & shLotList.Cells(1, 16) & "_1440x1080.ijm"
xActionMarco1 = "open("""
xActionMarco2 = """);"
xMarcoPath = Replace(path, "\", "\\")
'''''下述代码是利用VBA将Java代码写成Image J可以运行的脚本
'''''***值得注意的是,利用Image J转换图片格式需注意图片本身的bite数和分辨率***
Open ppFileName For Output As #1
For i = 1 To Total_lot_Count
' Print #1, "open(""" & IIf(Right(xMarcoPath, 1) <> "\\", xMarcoPath & "\\", xMarcoPath) & shLotList.Cells(i + 1, 1) & """);"
Print #1, "run(""Raw..."",""open=[" & IIf(Right(xMarcoPath, 1) <> "\\", xMarcoPath & "\\", xMarcoPath) & shLotList.Cells(i + 1, 1) & "] image=[16-bit Unsigned] width=1440 height=1080 offset=0 number=1 gap=0 little-endian"");"
Print #1, "run(""Appearance..."", ""antialiased menu=15 16-bit=[10-bit (0-1023)]"");"
' Debug.Print "run(""Bandpass Filter..."", ""filter_large=40 filter_small=3 suppress=None tolerance=5 autoscale saturate"");"
xNewFileName = Replace(shLotList.Cells(i + 1, 1), ".raw", "." & shLotList.Cells(1, 16))
Print #1, "saveAs(""BMP""" & ",""" & IIf(Right(xMarcoPath, 1) <> "\\", xMarcoPath & "\\", xMarcoPath) & xNewFileName & """);"
Print #1, "run(""Bandpass Filter..."", ""filter_large=40 filter_small=3 suppress=None tolerance=5 autoscale saturate"");"
Print #1, "saveAs(""BMP""" & ",""" & IIf(Right(xMarcoPath, 1) <> "\\", xMarcoPath & "\\", xMarcoPath) & "Enhanced" & xNewFileName & """);"
Print #1, "close();"
Next
Close #1
End Sub
Sub Image_Output()
Call clearsheet
Set shimage = Worksheets("Image_List")
Set shLotList = Worksheets("lot_list")
DATALOG_PATH = IIf(Right(shLotList.Cells(1, 2), 1) <> "\", shLotList.Cells(1, 2) & "\", shLotList.Cells(1, 2))
CheckFileName = "*." & shLotList.Cells(1, 16)
' BmpFilename = Dir(DATALOG_PATH & CheckFileName
i_list = 2
i = 0
For i_list = 2 To shLotList.Cells(i_list, 1).End(xlDown).Row
If shLotList.Cells(i_list, 1) <> "" Then
BmpFilename = Left(shLotList.Cells(i_list, 1), Len(shLotList.Cells(i_list, 1)) - 4) & ".bmp"
BmpEnhanced = "Enhanced" & Left(shLotList.Cells(i_list, 1), Len(shLotList.Cells(i_list, 1)) - 4) & ".bmp"
End If
shimage.Activate
Dim varRow, PicCol, PicFileName, PicPath, PicLeft, PicTop, PicWidth, PicHeight
PicCol = 2
varRow = 0
' Do While BmpFilename <> ""
shimage.Cells(i * 2 + 1, varRow + 2) = BmpFilename: shimage.Cells(i * 2 + 1, varRow + 3) = BmpEnhanced
shimage.Rows(i * 2 + 2).Select
Cells(2 * i + 2, varRow + 2).RowHeight = 113
Cells(2 * i + 2, varRow + 2).ColumnWidth = 18.75
PicLeft = Cells(2 * i + 2, varRow + 2).Left
PicTop = Cells(2 * i + 2, varRow + 2).Top
PicWidth = Cells(2 * i + 2, varRow + 2).Width
PicHeight = Cells(2 * i + 2, varRow + 2).Height
ActiveSheet.Shapes.AddPicture DATALOG_PATH & BmpFilename, msoFalse, msoTrue, PicLeft, PicTop, PicWidth, PicHeight
PicLeft = 0.75
PicTop = 0.75
PicWidth = 113.25
PicHeight = 84.75
shimage.Rows(i * 2 + 3).Select
Cells(2 * i + 2, varRow + 3).RowHeight = 113
Cells(2 * i + 2, varRow + 3).ColumnWidth = 18.75
PicLeft = Cells(2 * i + 2, varRow + 3).Left
PicTop = Cells(2 * i + 2, varRow + 3).Top
PicWidth = Cells(2 * i + 2, varRow + 3).Width
PicHeight = Cells(2 * i + 2, varRow + 3).Height
ActiveSheet.Shapes.AddPicture DATALOG_PATH & BmpEnhanced, msoFalse, msoTrue, PicLeft, PicTop, PicWidth, PicHeight
PicLeft = 0.75
PicTop = 0.75
PicWidth = 113.25
PicHeight = 84.75
i = i + 1
Next
End Sub
Sub clearsheet()
Set shLotList = Worksheets("lot_list")
Set Image_List = Worksheets("Image_List")
Image_List.Select
Image_List.Rows("1:65534").Select
Selection.ClearContents
Image_List.Range("A1").Select
Dim Sh As Shape
With Worksheets("Image_List")
For Each Sh In .Shapes
Sh.Delete
Next Sh
End With
shLotList.Activate
End Sub
将目标路径填入”B1"单元格,按钮“Start”对应代码“Find_Lot_List”模块的代码,按钮“Image Output”对应“Image_Output”模块的代码。
点击“Start”运行上述代码,可以获取指定路径下的Raw图片文件和测试时间。
在获取每张raw图片名称的同时也将执行指令写入了Ijm文件。
鼠标右键编辑打开ijm文件,可以看到VBA逐行写入的macro指令;值得一提的是,此处的代码是基于java书写的,如果对于该语言不熟悉的人可以利用Image J录制操作的办法获取对应的macro代码[2,3]。
点击Image J的Plugins >> Macro >>Run选项卡,然后将上述Ijm文件的路径填进去,即可运行该脚本;或者直接将Ijm文件用鼠标拖拽至软件选项卡上,即可运行该脚本。
待图片逐张处理结束,可以看到目标文件夹下多了bmp格式和Enhanced后的图片(Enhanced操作是指增加了图片的对比度,对应的手动操作是Image J打开Raw格式图片 >>Process >> FFT >>Bandpass Filter, 该图片处理方法作为示范,其他操作可以参照Image J的用法[4],代码可以参考Macro录制的办法。)
在得到上述图像后,点击“Image Output”按钮把Raw转换后的Bmp和进一步处理后的 Bmp图片成组地按照测试时间顺序放在excel指定位置上,同时名称写入每个图片上方单元格作为标识。
完成以上的操作后,即可以实现批量将Raw图片格式转换成Bmp格式(其他格式转换也同理),同时也可以针对图片批量进一步处理(比如增强对比),最后可以将处理后的图片按照测试时间的顺序放在指定的Excel中,能够高效快速得到图片的识别和对比效果。
在文章的最后,所有关于Image J软件的使用,都推荐使用Image J 官方说明文档,里面有详细的用法解释和数以千计的实例参考,如果阅读起来有困难的可以参考CSDN或者网页上各位作者写的专题文章。
参考阅读文章:
[1]Image J 百度介绍
[2] ImageJ实用技巧——宏记录器(解放双手篇)
[3]ImageJ脚本初步:宏录制
[4]Image J官方说明文档