×

LabelImg 图片标注工具 for Mac

96
SpikeKing
2018.05.28 10:21* 字数 1790
LabelImg

图片标注(Image Annotation)是物体检测等工作的基础,就是使用矩形框标注出图片中的物体,同时指定合适的标签。目前,比较常用的标注工具就是LabelImg。LabelImg提供可视化的标注操作界面,将图片的标注信息存入同名的XML文件中。

欢迎Follow我的GitHubhttps://github.com/SpikeKing

在LabelImg工程的主页,有一行对于操作系统的说明:

macOS

即目前的可执行文件,仅支持Windows和Linux,macOS需要从源码构建应用。那么,如何在Mac中构建LabelImg应用呢?

已编译完成的LabelImg的下载地址,在Mac中,可以直接使用。

GitHub

LabelImg是一个GitHub的开源工程,除了源码之外,还有一些应用图标和链接库等文件,导致工程较大,下载较慢。

其实,GitHub的下载链接是自带加速功能,由于国内的域名污染,在访问链接时,需要跨越较多的无效域名,导致下载较慢,参考。因此,找到GitHub的真实地址,直接访问,就可以加快下载速度。这个方法,也适用于访问其他较慢的国外下载链接。

找到国外域名的真实IP地址,可以直接使用IPAddress,或访问lookup接口均可。

IPAddress

输入域名,即可查询真实的IP地址,例如查询github.com

IP

注意:查询的IP地址可能会不同,一般而言,直接使用国外的IP地址,比使用国内域名服务器的地址,能够获得更快下载速度。

与GitHub相关的域名有两个,即:

  • github.com:真实IP 192.30.253.xxx;
  • github.global.ssl.fastly.net:真实IP 151.101.13.xxx;

查询完成之后,将域名和域名真实IP,写入Mac的hosts文件中,由于hosts是系统文件,需要获取管理员权限sudo进行写入:

sudo vi /etc/hosts

在hosts的末尾添加:

192.30.253.xxx  github.com
151.101.13.xxx  github.global.ssl.fastly.net
159.122.18.xxx  dl.bintray.com

除GitHub的链接之外,也可以添加其他国外域名的IP,如dl.bintray.com等。

Conda

在Pip源中,Qt的相关包安装异常,因而,使用Conda源作为Python环境。Conda与Pip的功能类似,近似于Pip与Virtualenv的结合,用于隔离Python的系统环境。由于仅仅使用Conda的Python功能,直接安装Conda的Miniconda版本即可,选择Python 2.7版本。

Miniconda

Conda的Python版本是编译Conda功能所用的版本,与Conda所创建虚拟环境的Python版本无关,也就是说,Python 2.7版本的Conda也可以创建Python 3.6版本的虚拟环境。

下载Miniconda的sh脚本,直接执行即可,安装目录位于~/miniconda2中,conda可执行文件位于miniconda2的bin文件夹下,其中就包含conda命令。由于Conda的系统环境设置问题,导致覆盖原有的Python命令路径,需要修改终端配置。

终端

终端shell是oh-my-zsh,即zsh终端。在zsh终端启动时,执行.zshrc脚本。因此,在.zshrc的末尾添加:

source ~/.bash_profile

即执行.bash_profile脚本。

将定制的环境配置,添加至.bash_profile中,用于在zsh中执行:

  • 将定制的可执行文件夹~/bin放入系统路径PATH中;
  • 将Python路径PYTHONPATH指定为系统的python;
  • 修改Miniconda2配置,将默认Python路径位于miniconda2/bin路径之前,防止干扰;

即:

export PATH="$PATH:/Users/[name]/bin"
export PYTHONPATH="/usr/local/bin/python"

# added by Miniconda2 installer
export PATH="$PATH:/Users/[name]/miniconda2/bin"

~/bin中,创建conda的软链接:

ln -s conda /Users/[name]/miniconda2/bin/conda

conda -> /Users/[name]/miniconda2/bin/conda

最后,执行source ~/.bash_profile或重启终端,将命令导入至shell环境,直接输入conda即可运行命令,

shell的调用流程:zsh -> .zshrc -> .bash_profile -> bin -> conda。

其他shell命令的添加方法,与此类似。

操作

conda创建虚拟环境,如Python 3.x版本的py3,

conda create -n py3 python=3
source activate py3

虚拟环境py3位于miniconda2/envs/中,如果重名,删除即可。

安装Python包:

conda install pyqt

取消激活环境

source deactivate

conda的操作简单便捷,如果一些pip源的包没有收录至conda源,可以在Google中搜索conda的个人源。

其他Conda命令,请参考

加速

conda源位于国外,速度较慢,可以切换为国内的清华镜像,执行以下设置即可。

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes

conda的config文件位于~/.condarc中。

LabelImg

系统环境已经配置完成,GitHub和Conda均可高效使用,可以开始构建LabelImg项目了。

在GitHub中下载labelImg工程:

git clone https://github.com/tzutalin/labelImg.git

创建conda的Python虚拟环境,下载依赖包,参考,环境是Qt5 + Python 2:

conda create -n py2 python=2
source activate py2
conda install qt
conda install pyqt
conda install libxml2
conda install lxml
make qt5
python labelImg.py

其中的conda安装qt,也可以替换为brew安装

conda install qt
conda install pyqt
或
brew install qt
brew install pyqt

labelImg.py是程序入口,最终的启动效果:

LabelImg

错误梳理

为什么不使用Qt4?

因为Qt4与Mac系统的10.13(High Sierra)版本兼容性不好,可以编译成功,但是无法读取jpeg等类型的图片,所以只能选择Qt5进行编译。

为什么安装和编译的是Qt5,却显示找不到Qt4?

提示找不到Qt4的Bug,如下:

Traceback (most recent call last):
  File "labelImg.py", line 1453, in <module>
    sys.exit(main())
  File "labelImg.py", line 1449, in main
    app, _win = get_main_app(sys.argv)
  File "labelImg.py", line 1442, in get_main_app
    argv[3] if len(argv) >= 4 else None)
  File "labelImg.py", line 98, in __init__
    self.settings.load()
  File "/Users/wang/exercises/labelImg/libs/settings.py", line 33, in load
    self.data = pickle.load(f)
  File "/Users/wang/miniconda2/envs/py2/lib/python2.7/pickle.py", line 1384, in load
    return Unpickler(file).load()
  File "/Users/wang/miniconda2/envs/py2/lib/python2.7/pickle.py", line 864, in load
    dispatch[key](self)
  File "/Users/wang/miniconda2/envs/py2/lib/python2.7/pickle.py", line 1139, in load_reduce
    value = func(*args)
ImportError: No module named PyQt4.QtCore

原因是,代码中导入包的异常处理,当无法加载Qt5时,就选择加载Qt4,这段逻辑简直无厘头,看似聪明,实则干扰调试,也不提示“无法找到 Qt5”的异常,让开发者误以为还要安装Qt4。

try:
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
except ImportError:
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *

实际上,Qt5并未直接安装至系统环境中,而是安装在Python的site-packages中,即:

/usr/local/lib/python2.7/site-packages/

将这个包的文件夹,导入至Python路径即可

export PYTHONPATH="$PYTHONPATH:/usr/local/lib/python2.7/site-packages/"

为什么包含两份Qt的二进制文件?

提示有两个Qt二进制文件的集合,如下:

objc[32802]: Class RunLoopModeTracker is implemented in both xxx and yyy. One of the two will be used. Which one is undefined.
QObject::moveToThread: Current thread (0x7fefa3512020) is not the object's thread (0x7fffb38b9380).
Cannot move to target thread (0x7fefa3512020)

You might be loading two sets of Qt binaries into the same process. Check that all plugins are compiled against the right Qt binaries. Export DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.
This application failed to start because it could not find or load the Qt platform plugin "cocoa"
in "".

Available platform plugins are: cocoa, minimal, offscreen.

Reinstalling the application may fix this problem.

原因是,在Mac系统中,使用brew安装一遍Qt,又使用conda安装一遍Qt,两个包重叠使用,卸载一个即可,优先卸载conda安装的Qt,执行以下操作:

brew install qt
brew install pyqt
conda uninstall pyqt
conda uninstall qt

为什么提示Qt4和Qt5同时存在?

提示同时使用PyQt4和PyQt5,如下:

Traceback (most recent call last):
  File "labelImg.py", line 1453, in <module>
    sys.exit(main())
  File "labelImg.py", line 1449, in main
    app, _win = get_main_app(sys.argv)
  File "labelImg.py", line 1442, in get_main_app
    argv[3] if len(argv) >= 4 else None)
  File "labelImg.py", line 98, in __init__
    self.settings.load()
  File "/Users/wang/exercises/labelImg/libs/settings.py", line 33, in load
    self.data = pickle.load(f)
  File "/Users/wang/miniconda2/envs/py2/lib/python2.7/pickle.py", line 1384, in load
    return Unpickler(file).load()
  File "/Users/wang/miniconda2/envs/py2/lib/python2.7/pickle.py", line 864, in load
    dispatch[key](self)
  File "/Users/wang/miniconda2/envs/py2/lib/python2.7/pickle.py", line 1139, in load_reduce
    value = func(*args)
RuntimeError: the PyQt4.QtCore and PyQt5.QtCore modules both wrap the QObject class

根据错误位置定位至settings.py的加载pkl数据操作,原因是.labelImgSettings.pkl文件可能是用Qt4生成的,删除即可,应用则会重新生成。

self.path = os.path.join(home, '.labelImgSettings.pkl')

还有类似的PyQt4和PyQt5同时存在的问题:

Traceback (most recent call last):
  File "labelImg.py", line 1453, in <module>
    sys.exit(main())
  File "labelImg.py", line 1449, in main
    app, _win = get_main_app(sys.argv)
  File "labelImg.py", line 1442, in get_main_app
    argv[3] if len(argv) >= 4 else None)
  File "labelImg.py", line 415, in __init__
    self.filePath = ustr(defaultFilename)
  File "/Users/wang/exercises/labelImg/libs/ustr.py", line 7, in ustr
    from PyQt4.QtCore import QString
RuntimeError: the PyQt4.QtCore and PyQt5.QtCore modules both wrap the QObject class

根据错误位置定位至ustr.py文件,原因是引用Qt4的包,直接注释或者使用Qt5重写这一段逻辑,即可。

import sys

def ustr(x):
    '''py2/py3 unicode helper'''

    if sys.version_info < (3, 0, 0):
        # from PyQt4.QtCore import QString
        if type(x) == str:
            return x.decode('utf-8')
        # if type(x) == QString:
        #     return unicode(x)
        return x
    else:
        return x  # py3

LabelImg图片标注工具并不完美,不过已经可以使用,为标注工作提供了便捷。

已编译完成的LabelImg的下载地址,在Mac中,可以直接使用。

OK, that's all! Enjoy it!

深度学习📒
Web note ad 1