【安装、配置、汉化】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>

新用户?&nbsp;

<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);

修改完的效果:

image.png

以此类推,每个页面都有对应的文件夹,例如项目: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时报错了

image.png

这个问题是在构建 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

image.png

这个错误信息表明在尝试通过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进行汉化欢迎讨论

部分界面汉化效果

image.png

image.png

在这里插入图片描述

在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。