【安装、配置、汉化】CVAT: 团队协作与自动标注的图像标注工具
Ice TeaJH 2024-08-16 12:01:03 阅读 94
哪里不会点哪里
CVAT简介安装配置CVATCVAT汉化修改图标修改代码重构docker镜像报错:未找到eb1ac09分支报错:安装软件错误2024年更新报错:git下载项目失败**2024/7/31更新报错:yarn "node"版本错误**2024/7/31更新报错:卡在[4/4] Building fresh packages...
启动镜像
部分界面汉化效果
本文记录了安装标注工具CVAT的过程,并且使用一种相当笨的方法进行汉化
CVAT简介
在人工智能领域,数据标注是构建高效机器学习模型的关键步骤之一。Computer Vision Annotation Tool (CVAT) 作为一款功能强大的开源标注工具。
CVAT有两大最关键的功能:支持团队协作标注;自动化标注。
这使得CVAT很适合当作人工智能团队的标注工具,但尽管CVAT提供了一个直观的在线版本,对于追求深度定制和团队使用的项目来说,本地部署则显得尤为重要。本地部署CVAT主要优势是允许团队根据具体业务需求进行二次开发,提升工具的适用性。
安装配置CVAT
CVAT项目团队已经将软件封装为Docker镜像,极大地简化了安装流程。遵循官方文档的指导,即便是新手也能顺利进行安装。然而,在实际操作中,网络状况可能会成为一道难以逾越的障碍,尤其是镜像下载环节。
github:https://github.com/cvat-ai/cvat
官方文档:https://docs.cvat.ai/docs/administration/basics/installation/
面对需要连接外网导致的镜像拉去失败,网上有许多资料,主要是更换镜像源或使用VPN。这些方法有时能奏效,但实际上就在不久之前,我使用这些方法也不能拉取镜像。近期,借助稳定且高速的网络环境,终于成功克服了这一难关,实现了CVAT的本地部署。
首先需要确保你的电脑安装了docker,接下来的流程对于windows和linux差别不大
最基础的安装:
使用 Git 从 GitHub 存储库克隆 CVAT 源代码。
以下命令将克隆最新的开发分支:
<code>git clone https://github.com/cvat-ai/cvat
cd cvat
如果要使用网络或通过其他系统访问 CVAT,这一步是多台电脑进行团队协作的关键,如果不更改只能在自己的电脑上使用,需要导出环境变量CVAT_HOST
,不同系统方法略有不同
linux:
export CVAT_HOST=你的ip
windows:
SET CVAT_HOST=你的ip
然后进行构建镜像,也就是这一步需要使用VPN(网上资料说换源可以,但我自己试一试不行,甚至vpn有时也不行),反正主要还是取决于网络
2024/07/29 今日在服务器上配置时,发现换源还是可以的,不过可能一些镜像源被下架了什么的附上进入成功几个镜像源(不知道哪个成功的),如果又不行就再去找找其他镜像源:
https://hub.uuuadc.top/,
https://docker.anyhub.us.kg/,
https://dockerhub.jobcher.com/,
https://dockerhub.icu/,
https://docker.ckyl.me/,
https://docker.awsl9527.cn/
换源的方法就是修改docker.json,网上找找就有
docker compose up -d
等待构建成功后就可以直接使用了,如果之前设置了ip,就使用http://ip:8080;如果没有设置,就使用http://localhost:8080就能登陆CVAT,注意要将ip换成你刚刚设置的环境变量,其他的电脑也是直接访问这个网站。
普通注册一个用户时,默认没有查看任务列表的权限。为此,可以创建一个超级用户。超级用户可以使用 管理员面板,用于将正确的组分配给其他用户。请使用以下命令 下面:
sudo docker exec -it cvat_server bash -ic 'python3 ~/manage.py createsuperuser'
在windows中建议直接使用以下这个,一样的效果
#进入镜像
docker exec -it cvat_server /bin/bash
#运行程序
python3 ~/manage.py createsuperuser
CVAT汉化
搜索网上的资料以及项目中的issues,对界面进行汉化有很多种方法,比如使用gettext、使用i8next等方法,但我尝试以上两种方法暂没有成功,应该是坏境的问题。由于我没有前端经验,对于相关工作了解较少,以下应该是最简单但较麻烦的一种实现(直接找到对应的文本进行修改),主要在主文件夹中的cvat-ui文件夹里进行修改
项目的作者似乎从19年就开始做相关的工作,在issues中,可以关注官方是否推出其他语言支持
修改图标
在修改cvat-ui->dist中可以修改网站的图标
在cvat-ui>src>assets中修改其他图标
修改代码
主要的界面代码都在cvat-ui>src->components文件夹中
在components文件夹中寻找,发现login-page等文件夹可能和登录页面有关,修改即可。
比如修改login-page文件夹中的login-form.tsx代码,把所有英文文本换为中文
<code>import React, { -- --> useState } from 'react';
import { Link } from 'react-router-dom';
import Form from 'antd/lib/form';
import Button from 'antd/lib/button';
import Input from 'antd/lib/input';
import { Col, Row } from 'antd/lib/grid';
import Title from 'antd/lib/typography/Title';
import Text from 'antd/lib/typography/Text';
import Icon from '@ant-design/icons';
import {
BackArrowIcon, ClearIcon,
} from 'icons';
import CVATSigningInput, { CVATInputType } from 'components/signing-common/cvat-signing-input';
import { CombinedState } from 'reducers';
import { useAuthQuery, usePlugins } from 'utils/hooks';
export interface LoginData {
credential: string;
password: string;
}
interface Props {
renderResetPassword: boolean;
renderRegistrationComponent: boolean;
renderBasicLoginComponent: boolean;
fetching: boolean;
onSubmit(loginData: LoginData): void;
}
function LoginFormComponent(props: Props): JSX.Element {
const {
fetching, onSubmit, renderResetPassword, renderRegistrationComponent, renderBasicLoginComponent,
} = props;
const authQuery = useAuthQuery();
const [form] = Form.useForm();
const [credential, setCredential] = useState('');
const pluginsToRender = usePlugins(
(state: CombinedState) => state.plugins.components.loginPage.loginForm,
props,
{ credential },
);
let resetSearch = authQuery ? new URLSearchParams(authQuery).toString() : '';
if (credential.includes('@')) {
const updatedAuthQuery = authQuery ? { ...authQuery, email: credential } : { email: credential };
resetSearch = new URLSearchParams(updatedAuthQuery).toString();
}
const forgotPasswordLink = (
<Col className='cvat-credentials-link'>code>
<Text strong>
<Link to={ -- -->{ pathname: '/auth/password/reset', search: resetSearch }}>
忘记密码?
</Link>
</Text>
</Col>
);
return (
<div className='cvat-login-form-wrapper'>code>
<Row justify='space-between' className='cvat-credentials-navigation'>code>
{ -- -->
credential && (
<Col>
<Icon
component={ BackArrowIcon}
onClick={ () => {
setCredential('');
form.setFieldsValue({ credential: '' });
}}
/>
</Col>
)
}
{
!credential && renderRegistrationComponent && (
<Row>
<Col className='cvat-credentials-link'>code>
<Text strong>
新用户?
<Link to={ -- -->{
pathname: '/auth/register',
search: authQuery ? new URLSearchParams(authQuery).toString() : '',
}}
>
注册账户
</Link>
</Text>
</Col>
</Row>
)
}
{
renderResetPassword && forgotPasswordLink
}
</Row>
<Col>
<Title level={ 2}> 登录 </Title>
</Col>
<Form
className={ `cvat-login-form ${ credential ? 'cvat-login-form-extended' : ''}`}
form={ form}
onFinish={ (loginData: LoginData) => {
onSubmit(loginData);
}}
>
{ renderBasicLoginComponent && (
<>
<Form.Item
className='cvat-credentials-form-item'code>
name='credential'code>
>
<Input
autoComplete='username'code>
prefix={ -- --><Text>邮箱或用户名</Text>}
className={ credential ? 'cvat-input-floating-label-above' : 'cvat-input-floating-label'}
suffix={ credential && (
<Icon
component={ ClearIcon}
onClick={ () => {
setCredential('');
form.setFieldsValue({ credential: '', password: '' });
}}
/>
)}
onChange={ (event) => {
const { value } = event.target;
setCredential(value);
if (!value) form.setFieldsValue({ credential: '', password: '' });
}}
/>
</Form.Item>
{
credential && (
<Form.Item
className='cvat-credentials-form-item'code>
name='password'code>
rules={ -- -->[
{
required: true,
message: '请输入密码',
},
]}
>
<CVATSigningInput
type={ CVATInputType.PASSWORD}
id='password'code>
placeholder='密码'code>
autoComplete='current-password'code>
/>
</Form.Item>
)
}
{ -- -->
!!credential && (
<Form.Item>
<Button
className='cvat-credentials-action-button'code>
loading={ -- -->fetching}
disabled={ !credential}
htmlType='submit'code>
>
下一步
</Button>
</Form.Item>
)
}
</>
)}
{ -- -->
pluginsToRender.map(({ component: Component }, index) => (
<Component targetProps={ props} targetState={ { credential }} key={ index} />
))
}
</Form>
</div>
);
}
export default React.memo(LoginFormComponent);
修改完的效果:
以此类推,每个页面都有对应的文件夹,例如项目:project,任务:task,作业:job;哪个页面没有汉化就找对应的文件夹,进入修改相关文件
但要注意不要修改到类名等位置,只修改文本,否则项目容易无法运行
重构docker镜像
修改完代码需要从本地对镜像进行重构,否则无法得到新的docker镜像
根据官方文档中,运行以下命令停止并删除所有容器
<code>docker compose down
在修改过代码的主文件夹中重新构建docker镜像
docker compose -f docker-compose.yml -f docker-compose.dev.yml build
我在构建时依然需要使用VPN,并且在构建时遇到一些问题,可以进行参考:
报错:未找到eb1ac09分支
运行dockerfile时报错了
这个问题是在构建 Docker 镜像的过程中,<code>git checkout eb1ac09 命令未能找到指定的提交哈希值,可能是因为 Git 仓库中不存在 eb1ac09
这个特定的提交记录。
尝试改了几次dockerfile依然报错,则将它换成拉取最新的分支
# 确保仓库是最新的
RUN cd smokescreen && \
git fetch --all && \
git checkout main && \
go build -o /tmp/smokescreen
报错:安装软件错误
解决了上一个报错,由于网络问题可能还会遇到以下错误
failed to solve: process “/bin/sh -c apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -yq curl g++ gcc git libgeos-dev libldap2-dev libsasl2-dev make nasm pkg-config python3-dev python3-pip libxml2-dev libxmlsec1-dev libxmlsec1-openssl && rm -rf /var/lib/apt/lists/*” did not complete successfully: exit code: 100
这个错误信息表明在尝试通过apt-get安装一系列软件包时遇到了问题,导致退出代码为100。在Debian和Ubuntu系统中,apt-get命令的退出代码100通常表示在处理依赖关系时遇到问题,可能是由于包之间的冲突、缺少依赖项或软件源中的问题。一般来说是由于网络问题
将dockerfile中的这段代码
<code>RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -yq \
bzip2 \
ca-certificates \
curl \
git \
libgeos-c1v5 \
libgl1 \
libgomp1 \
libldap-2.5-0 \
libpython3.10 \
libsasl2-2 \
libxml2 \
libxmlsec1 \
libxmlsec1-openssl \
nginx \
p7zip-full \
poppler-utils \
python3 \
python3-venv \
supervisor \
tzdata \
unrar \
&& ln -fs /usr/share/zoneinfo/${ TZ} /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata && \
rm -rf /var/lib/apt/lists/* && \
echo 'application/wasm wasm' >> /etc/mime.types
更换为以下代码
# 更改APT软件源到清华镜像站点
RUN sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list && \
sed -i 's/security.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list
# 更新软件包列表并安装所需软件包
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -yq \
bzip2 \
ca-certificates \
curl \
git \
libgeos-c1v5 \
libgl1 \
libgomp1 \
libldap-2.5-0 \
libpython3.10 \
libsasl2-2 \
libxml2 \
libxmlsec1 \
libxmlsec1-openssl \
nginx \
p7zip-full \
poppler-utils \
python3 \
python3-venv \
supervisor \
tzdata \
unrar \
&& ln -fs /usr/share/zoneinfo/${ TZ} /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata && \
rm -rf /var/lib/apt/lists/* && \
echo 'application/wasm wasm' >> /etc/mime.types
2024年更新报错:git下载项目失败
在服务器上配置时,重新构建镜像经常失败,有一项报错为git下载datumaro失败
根据报错信息,在cvat\requirements中找到base.txt和base.in,其中有一句代码:
datumaro @ git+https://github.com/cvat-ai/datumaro.git@82982b16b178eb3f39c707795bb68a3306610abf
根据名字去gitee中找对应的项目,以下举例一种,如果失败了可以找找其他的
更换为:
datumaro @ git+https://gitee.com/tianyue_688/datumaro.git@82982b16b178eb3f39c707795bb68a3306610abf
2024/7/31更新报错:yarn "node"版本错误
在服务器进行构建镜像时,报了以下错误:
根据报错信息显示是node.js版本不符合导致,尝试了多个方法后,发现使用忽略报错的方式有效:
在dockerbuild.ui中找到报错的位置
<code>RUN DISABLE_HUSKY=1 yarn --frozen-lockfile
在这一句的上方添加:
RUN yarn config set ignore-engines true
这是忽略yarn报错的指令,虽然我也担心忽略报错会有影响,不过实测能够解决这个问题,成功构建
2024/7/31更新报错:卡在[4/4] Building fresh packages…
同样是上一个报错中的位置,当不报版本错误后,building的时候直接卡住,不继续往下走了
收集资料后发现,在当前文件夹即主文件夹中添加一个文件
.yarnrc
注意文件名要对,然后在这个文件中加入以下内容:
registry "https://registry.npm.taobao.org"
sass_binary_site "https://npm.taobao.org/mirrors/node-sass/"
phantomjs_cdnurl "http://cnpmjs.org/downloads"
electron_mirror "https://npm.taobao.org/mirrors/electron/"
sqlite3_binary_host_mirror "https://foxgis.oss-cn-shanghai.aliyuncs.com/"
profiler_binary_host_mirror "https://npm.taobao.org/mirrors/node-inspector/"
chromedriver_cdnurl "https://cdn.npm.taobao.org/dist/chromedriver"
重新构建则可以解决问题(不过网上也有些人说这个方法没用,我是加入后直接解决了,可供参考)
启动镜像
一般来说可以成功,多尝试几次就可以完成构建
然后启动容器
docker compose up -d
重新设置外部访问
export CVAT_HOST=190.168.xxx.xxx
但这却是是一种傻方法,费时费力,如果有更快的方法对CVAT进行汉化欢迎讨论
部分界面汉化效果
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。