用wxPython编写图像情感标注工具并编译成exe文件
该标注工具可以选择执行Python文件,也可以选择双击编译好的exe文件,还可以修改Python文件,新建虚拟环境并重新编译exe文件。
界面如下:
1.Python代码
- 新建虚拟环境,安装wxPython、pandas。
- 把Python文件放到与“图片xxx”文件夹同目录的地方,代码会读取文件夹中的PNG图片,并在与Python文件同目录的地方生成VA.csv文件。
- cmd窗口中进入该目录,执行python biaozhu.py
import wx
import os
import pandas as pd
import random
IMG_EXTENSIONS = [
# '.jpg', '.JPG', '.jpeg', '.JPEG',
# '.png', '.PNG', '.ppm', '.PPM', '.bmp', '.BMP',
'.png', '.PNG' # 下面加载图像部分只设置了PNG格式
]
def is_image_file(filename):
return any(filename.endswith(extension) for extension in IMG_EXTENSIONS)
def make_dataset(dir, max_dataset_size=float("inf")):
images = []
assert os.path.isdir(dir), '%s is not a valid directory' % dir
for root, _, fnames in sorted(os.walk(dir)):
for fname in fnames:
if is_image_file(fname):
# path = os.path.join(root, fname)
images.append(fname) # 101.png
return images[:min(max_dataset_size, len(images))]
def GetImageList(path='.'):
dirs = []
for root, dirs, files in os.walk(path):
dirs = dirs # 一次循环,只要当前目录的子目录
break
if dirs == []:
return None
else:
for dir1 in dirs:
if '图片' in dir1:
dir1 = os.path.join(path, dir1)
image_list = make_dataset(dir1)
return dir1, image_list
return None
def GetCsv(file_name = 'VA.csv'): # 读取VA.csv文件,获取图像名称列表
HEADER=['name','v','a']
if os.path.exists(file_name):
data = pd.read_csv(file_name, skiprows=1, names=HEADER)
image_list = data['name'].tolist()
v_list = data['v'].tolist()
a_list = data['a'].tolist()
dir, _ = GetImageList()
return dir,image_list,v_list,a_list
else:
dir, image_list = GetImageList()
random.shuffle(image_list)
v_list = [1.0]*len(image_list)
a_list = [1.0]*len(image_list)
dataframe = pd.DataFrame({'name':image_list,'v':v_list, 'a':a_list})
dataframe.to_csv(file_name,index=False,sep=',')
return dir,image_list,v_list,a_list
class Demo(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,None,wx.ID_ANY,"标注VA值",size =(600, 650))
self.dir, self.image_list, self.v_list, self.a_list = GetCsv()
self.index = 0
self.length = len(self.image_list)
print(self.dir)
panel = wx.Panel(self, -1)
##############################################################
multiStr ="选择VA值后点击下一张。\nVA.csv文件在同一目录下。\n每次启动都会重覆盖原数据。\n但只有结束或按写入文件才会把数据写入文件。"
text1 = wx.StaticText(panel,
wx.ID_ANY,
multiStr,
(10, 10))
file_name = os.path.join(self.dir, self.image_list[self.index]) # 第一张图像的地址
image = wx.Image(file_name, wx.BITMAP_TYPE_PNG) # 读取PNG图像
temp = image.ConvertToBitmap()
size = temp.GetWidth(), temp.GetHeight()
self.bmp = wx.StaticBitmap(panel, -1, temp, pos=(0, 90),size=size)
self.button1 = wx.Button(panel, -1, u"下一张", pos=(400, 50))
self.Bind(wx.EVT_BUTTON, self.OnClick1, self.button1)
self.button1.SetDefault()
self.button2 = wx.Button(panel, -1, u"写入文件", pos=(500, 50))
self.Bind(wx.EVT_BUTTON, self.OnClick2, self.button2)
self.button2.SetDefault()
sampleList1 = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
self.radiobox1 = wx.RadioBox(panel, -1, "V=1是非常消极,V=9是非常积极", (10, 500), wx.DefaultSize,
sampleList1, 9, wx.RA_SPECIFY_COLS)
sampleList2 = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
self.radiobox2 = wx.RadioBox(panel, -1, "A=1是非常平静,A=9是非常兴奋", (10, 550), wx.DefaultSize,
sampleList2, 9, wx.RA_SPECIFY_COLS)
def GetRadioData(self):
v = int(self.radiobox1.GetStringSelection()) # 获得被选择的符号并转成整数
self.v_list[self.index] = v
a = int(self.radiobox2.GetStringSelection())
self.a_list[self.index] = a
def SaveData(self,file_name = 'VA.csv'):
dataframe = pd.DataFrame({'name':self.image_list,'v':self.v_list, 'a':self.a_list})
dataframe.to_csv(file_name,index=False,sep=',')
def OnClick1(self, event):
# print("本次选择了%s,index=%d" %(self.radiobox.GetStringSelection(), self.radiobox.GetSelection()))
if self.index == self.length - 1:
self.GetRadioData()
self.SaveData()
self.Close(True) # 关闭窗口
else:
self.GetRadioData()
self.index = self.index + 1
file_name = os.path.join(self.dir, self.image_list[self.index])
image = wx.Image(file_name, wx.BITMAP_TYPE_PNG)
temp = image.ConvertToBitmap()
self.bmp.SetBitmap(temp) # 更新展示的图像
def OnClick2(self,event):
self.GetRadioData()
self.SaveData()
# print('get and save data')
if __name__ == '__main__':
# image_list = GetImageList()
app = wx.App()
frame = Demo()
frame.Show(True)
app.MainLoop()
2.在虚拟环境中编译成exe文件
- 打包的时候如果没有新建虚拟环境,很多无关的库也会被打包进去,结果exe文件就会很大,达到327M,双击以后1分钟才能出现图像界面。新建虚拟环境再打包就只剩33M。exe文件放在与Python文件同目录的地方,双击一下就行。
- 打包:
新建虚拟环境,conda和pipenv都可以(如果前一步是在虚拟环境中执行Python代码那就不需要再新建)。conda info --env查看已有虚拟环境,conda create --name wx python=3.6创建名为wx的虚拟环境,activate wx和deactivate wx分别是win10启动和退出虚拟环境, conda[pip] install wxPython pandas pyinstaller安装需要的库,conda list查看已安装的库,conda remove -n wx --all删除虚拟环境。
确认代码可以执行以后,用pyinstaller打包成exe文件,pyinstaller -F biaozhu.py。