Skip to content
This repository has been archived by the owner on Mar 10, 2023. It is now read-only.

A python-based questionnaire server to get user's classification of images.

License

Notifications You must be signed in to change notification settings

fumiama/image-classification-questionnaire-server

Repository files navigation

Ichiko

图像分类问卷调查服务器(ICQS)

基于go/python的图像分类调查服务器

用户可以利用api自己上传图像并指定分类,也可以从服务器的图像中查看图片,并指定分类。

使用准备

Python准备

你需要安装pillownumbaimagehashquart/flask, gevent(如果使用flask)等包以确保程序运行。

pip install -r requirements.txt

Golang准备

由于整合了setu-class,你需要编译安装setu-class-cpp库,该库要求您已经安装了libtorch。然后,请将该仓库的ero.ptnor.pt复制到本项目编译出的可执行文件旁。

另外,您还需要部署一个simple-storage,命令行参数中需要填写其apiurlauthkey

接下来安装libwebp-dev,并在使用前运行

go mod tidy

开始使用

首先克隆本仓库

git clone --depth=1 https://github.com/fumiama/image-classification-questionnaire-server.git

Golang版

1. 命令行参数

  1. 如果你是ubuntu用户,由于该系统绑定80端口需要root权限,因此需要添加可选参数userid以在绑定端口后降权运行。
  2. 密码必须为两个汉字,在运行后密码将在命令行被隐藏,但不会清除命令历史记录,请手动清除。
Usage: <listen_addr> <apiurl> <password> <authkey> <dbfile> (userid) &

注意:

  1. 如果添加末尾的&,程序将会以daemon运行。
  2. userid为可选项。如果设置,程序将会在绑定端口后切换到该uid处理请求。
  3. Windows下使用不支持userid选项。
  4. dbfile位置任意。

2. 编译

  • 如果使用gc,添加-ldflags "-s -w"编译即可。
  • 如果使用gccgo,推荐使用如下优化参数以达到最佳效果。
go build -compiler gccgo -gccgoflags "-Wa,--strip-local-absolute,-R -s -Wl,-x,-X,--sort-common,--enable-new-dtags,--hash-style=gnu -fno-bounds-check -freg-struct-return -O3" -o im

Python版

  1. 如果你是ubuntu用户,由于该系统绑定80端口需要root权限,因此需要添加可选参数server_uid以在绑定端口后降权运行。
  2. 密码文件pwd_path必须为以UTF16BE编码存储的两个汉字(包括文件头0xfeff),总长6字节。

简易版server.py的语法如下

注意:使用一段时间后可能会无响应,目前尚未解决,只能通过daemon.sh监控进程是否退出,如果退出则重新拉起。

./server.py [-d] <user_dir> <image_dir> <pwd_path> (server_uid)

其中:

  1. -d为可选项,如果设置,程序将会以daemon运行。
  2. server_uid为可选项。如果设置,程序将会在绑定端口后切换到该uid处理请求。

Quart/Flaskserver_quart/flask.py的语法如下(高并发)

./server_quart/flask.py <user_dir> <image_dir> <pwd_path> (server_uid) 2>&1 > ./log.txt &

其中:

  1. 如果添加末尾的&,程序将会以daemon运行。
  2. server_uid为可选项。如果设置,程序将会在绑定端口后切换到该uid处理请求。

注意:

  1. 服务端图片扩展名只接受.webp,客户端上传时任意。如需其它格式请自行修改代码。
  2. 图片的唯一标识使用了该图片dhash值的base16384编码的前五个汉字。

Golang版API(推荐)

对应执行文件为server.go,该版本的class只能为0~7的整数。

0. 直接访问

  • 格式: http://[server_domain]/

  • 说明: 直接通过简易网页访问服务。

1. 注册用户

  • 格式: http://[server_domain]/signup?key=1234567890

  • 返回:

  1. 成功
{"stat":"success", "id":"%XX%XX%XX%XX%XX%XX"}
  1. 密码错误
{"stat":"wrong", "id":"null"}
  1. 处理错误
400 BAD REQUEST
  • 说明:
  1. 返回转义的两个utf-8编码的汉字,代表下面用到的uuid
  2. key后跟10位整数,表示密码与当前秒数异或的结果,与服务端相差10秒内有效

2. 指定分类(投票)

  • 格式: http://[server_domain]/vote?uuid=用户&img=投票的图片&class=n

  • 返回:

  1. 成功
{"stat":"success"}
  1. 图片名格式非法
{"stat":"invimg"}
  1. 用户名格式非法
{"stat":"invid"}
  1. 找不到uuid/img/class字段
400 BAD REQUEST
  1. class非法
{"stat":"invclass"}
  • 说明:
  1. uuid字段容纳两(数量不可增减)个utf-8编码的汉字,表示投票用户。
  2. img字段容纳五个(数量不可增减)utf-8编码的汉字,唯一标识了这张图片。
  3. class字段class只能为0~7的整数,代表该图片所属标签。

3. 下载图片

  • 格式: http://[server_domain]/img?path=某一张图片

  • 返回:

  1. 成功
图片数据
  1. 无此图片
{"stat":"nosuchimg"}
  1. 图片名格式非法
{"stat":"invimg"}
  • 说明: 目标的图片是五个(数量不可增减)utf-8编码的汉字,唯一标识了这张图片。

4. 上传图片

  • 格式: HTTP POST到http://[server_domain]/upload?uuid=用户

  • 返回:

  1. 成功
{"stat":"success","result":[{"stat": "success","img": "%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX"}]}
  1. 相似或相同图片存在
{"stat":"success","result":[{"stat":"exist","img":"%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX"}]}
  1. 空请求体
{"stat":"emptybody"}
  1. 找不到此用户
{"stat":"noid"}
  1. 解析dhash错误
{"stat":"success","result":[{"stat":"notanimg","img":""}]}
  1. 不是图片
{"stat":"success","result":[{"stat":"notanimg","img":""}]}
  1. io错误
{"stat":"success","result":[{"stat":"ioerr","img":""}]}
  1. 图片转码错误
{"stat":"success","result":[{"stat":"encerr","img":""}]}
  • 说明: 必须为webpjpgpnggif格式。使用wget时,可使用如下命令。
wget --post-file=image.webp http://[server_domain]/upload?uuid=用户

5. 以表单形式上传图片

该API无法上传合计大于64M的文件,可以更改ParseMultipartForm入参以提高上限

  • 格式: HTTP POST到http://[server_domain]/upform?uuid=用户

该格式支持批量上传。

  1. 成功 返回时,会将全部结果统一送回。
{"stat":"success","result":[{"name":"a.jpg","stat":"exist"},{"name":"b.jpg","stat":"exist"},{"name":"c.jpg","stat":"exist"},{"name":"d.jpg","stat":"success"},{"name":"e.jpg","stat":"success"}]}

其中,result列表的每一项都遵循条目4的result格式。 2. 找不到此用户

{"stat":"noid"}
  1. io错误
{"stat":"success","result":[{"stat":"ioerr","img":""}]}
  • 说明: 必须为webpjpgpnggif格式。

6. 从未投票图片中随机选择图片并返回图片数据

  • 格式: http://[server_domain]/pickdl?uuid=用户
  • 返回:
  1. 成功
图片数据
  1. 无更多图片
{"stat":"nomoreimg"}
  1. 无此用户
{"stat":"noid"}
  1. 用户名格式非法
400 BAD REQUEST
  • 说明: 用户是两个(数量不可增减)utf-8编码的汉字,唯一标识了某个用户。

7. 从未投票图片中随机选择图片并返回图片名

  • 格式: http://[server_domain]/pick?uuid=用户
  • 返回:
  1. 成功
{"stat":"success", "img":"%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX", "uploader":"%XX%XX%XX%XX%XX%XX"}
  1. 无更多图片
{"stat":"nomoreimg"}
  1. 无此用户
{"stat":"noid"}
  1. 用户名格式非法
400 BAD REQUEST
  • 说明:
  1. 用户是两个(数量不可增减)utf-8编码的汉字,唯一标识了某个用户。
  2. 返回的图片名经过了转义。

8. dice

参数详见setu-class

9. 获取图片 dhash

  • 格式: http://[server_domain]/dhash?pidp=pid_pn

  • 返回:

  1. 成功
{"PidP":"53538084_p0","UID":63652,"Width":650,"Height":906,"Title":"秋月照月本表紙","Author":"中乃空","R18":false,"Tags":"[\"艦隊これくしょん\",\"舰队collection\",\"C89\",\"秋月\",\"Akizuki\",\"照月\",\"Teruzuki\",\"艦ぱい\",\"shipgirl breasts\",\"尻神様\",\"尻神样\",\"即夜戦\",\"即将夜战\",\"秋月型\",\"Akizuki-class\",\"ねじ込みたい尻\",\"这屁股让人想肛\"]","Ext":"png","DatePath":"2015/11/14/00/28/41","DHash":"嗉聚裌蠼嬀","Md5":"34f4ed2a6500dc8c6822f0d4333639ba"}
  1. 失败
各种状态码,附带简短说明

简易版API(不建议用)

对应执行文件为server.py

0. 直接访问

  • 格式: http://[server_domain]/index.html

  • 说明: 直接通过简易网页访问服务。

1. 注册用户

  • 格式: http://[server_domain]/signup?1234567890

  • 返回: 成功(succ),密码错误(null),处理错误(erro)

  • 说明:

  1. 返回utf-8编码的两个汉字,代表下面用到的uuid
  2. 后跟10位整数,表示密码与当前秒数异或的结果,与服务端相差10秒内有效

2. 指定分类(投票)

  • 格式: http://[server_domain]/vote?uuid=用户&img=投票的图片&class=n

  • 返回: 成功(succ),错误(erro)

  • 说明:

  1. uuid字段容纳两(数量不可增减)个utf-8编码的汉字,表示投票用户。
  2. img字段容纳五个(数量不可增减)utf-8编码的汉字,唯一标识了这张图片。
  3. class字段容纳最多184个ASCII编码,代表该图片所属标签。

3. 下载图片

  • 格式: http://[server_domain]/目标的图片

  • 返回: 成功(图片数据),空(null),错误(erro)

  • 说明: 目标的图片是五个(数量不可增减)utf-8编码的汉字,唯一标识了这张图片。

4. 上传图片

  • 格式: HTTP POST到http://[server_domain]/upload?uuid=用户

  • 返回: 成功(succ),错误(erro),图片相似/无此用户(null)

  • 说明: 必须为webpjpgpnggif格式。使用wget时,可使用如下命令。

wget --post-file=image.webp http://[server_domain]/upload?uuid=用户

5. 从未投票图片中随机选择图片并返回图片数据

  • 格式: http://[server_domain]/pickdl?用户

  • 返回: 成功(图片数据),空(null),错误(erro)

  • 说明: 用户是两个(数量不可增减)utf-8编码的汉字,唯一标识了某个用户。

6. 从未投票图片中随机选择图片并返回图片名

  • 格式: http://[server_domain]/pick?用户

  • 返回: 成功(图片名),空(null),错误(erro)

  • 说明:

  1. 用户是两个(数量不可增减)utf-8编码的汉字,唯一标识了某个用户。
  2. 返回的图片名经过了转义。

Quart/Flask版API

对应执行文件为server_quart.py

0. 直接访问

  • 格式: http://[server_domain]/index.html

  • 说明: 直接通过简易网页访问服务。

1. 注册用户

  • 格式: http://[server_domain]/signup?key=1234567890

  • 返回:

  1. 成功
{"stat":"success", "id":"%XX%XX%XX%XX%XX%XX"}
  1. 密码错误
{"stat":"wrong", "id":"null"}
  1. 处理错误
{"stat":"error", "id":"null"}
  • 说明:
  1. 返回转义的两个utf-8编码的汉字,代表下面用到的uuid
  2. key后跟10位整数,表示密码与当前秒数异或的结果,与服务端相差10秒内有效

2. 指定分类(投票)

  • 格式: http://[server_domain]/vote?uuid=用户&img=投票的图片&class=n

  • 返回:

  1. 成功
{"stat":"success"}
  1. 图片名格式非法
{"stat":"invimg"}
  1. 用户名格式非法
{"stat":"invid"}
  1. 找不到此用户
{"stat":"noid"}
  • 说明:
  1. uuid字段容纳两(数量不可增减)个utf-8编码的汉字,表示投票用户。
  2. img字段容纳五个(数量不可增减)utf-8编码的汉字,唯一标识了这张图片。
  3. class字段容纳最多184个ASCII编码,代表该图片所属标签。

3. 下载图片

  • 格式: http://[server_domain]/img?path=某一张图片

  • 返回:

  1. 成功
图片数据
  1. 读图片错误
{"stat":"readimgerr"}
  1. 无此图片
{"stat":"nosuchimg"}
  1. 图片名格式非法
{"stat":"invimg"}
  • 说明: 目标的图片是五个(数量不可增减)utf-8编码的汉字,唯一标识了这张图片。

4. 上传图片

Quart版目前无法上传大于20M的图片

  • 格式: HTTP POST到http://[server_domain]/upload?uuid=用户

  • 返回:

  1. 成功
{"stat":"success", "img":"%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX"}
  1. 相似或相同图片存在
{"stat":"exist", "img":"%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX"}
  1. 用户名格式非法
{"stat":"invid"}
  1. 找不到此用户
{"stat":"noid"}
  1. 接收图片错误
{"stat":"recverr"}
  1. 不是图片
{"stat": "notanimg"}
  • 说明: 必须为webpjpgpnggif格式。使用wget时,可使用如下命令。
wget --post-file=image.webp http://[server_domain]/upload?uuid=用户

5. 以表单形式上传图片

该API目前无法上传合计大于20M的文件

  • 格式: HTTP POST到http://[server_domain]/upform?uuid=用户

该格式支持批量上传。

  • 返回:

返回时,会将全部结果统一送回。

{"result":[{"name":"a.jpg","stat":"exist"},{"name":"b.jpg","stat":"exist"},{"name":"c.jpg","stat":"exist"},{"name":"d.jpg","stat":"success"},{"name":"e.jpg","stat":"success"}]}

其中,列表的每一项都遵循如下格式

  1. 成功
{"name":"xxx","stat":"success"}
  1. 相似或相同图片存在
{"name":"xxx","stat":"exist"}
  1. 用户名格式非法
{"name":"xxx","stat":"invid"}
  1. 找不到此用户
{"name":"xxx","stat":"noid"}
  1. 接收图片错误
{"stat":"recverr"}
  1. 不是图片
{"stat": "notanimg"}
  • 说明: 必须为webpjpgpnggif格式。

6. 从未投票图片中随机选择图片并返回图片数据

  • 格式: http://[server_domain]/pickdl?uuid=用户

  • 返回:

  1. 成功
图片数据
  1. 读图片错误
{"stat":"readimgerr"}
  1. 无更多图片
{"stat":"nomoreimg"}
  1. 无此用户
{"stat":"noid"}
  1. 用户名格式非法
{"stat":"invid"}
  • 说明: 用户是两个(数量不可增减)utf-8编码的汉字,唯一标识了某个用户。

7. 从未投票图片中随机选择图片并返回图片名

  • 格式: http://[server_domain]/pick?uuid=用户

  • 返回:

  1. 成功
{"stat":"success", "img":"%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX", "uploader":"%XX%XX%XX%XX%XX%XX"}
  1. 读图片错误
{"stat":"readimgerr"}
  1. 无更多图片
{"stat":"nomoreimg"}
  1. 无此用户
{"stat":"noid"}
  1. 用户名格式非法
{"stat":"invid"}
  • 说明:
  1. 用户是两个(数量不可增减)utf-8编码的汉字,唯一标识了某个用户。
  2. 返回的图片名经过了转义。

小工具

一些实用的小工具放在了tools文件夹,包括批量上传图片,批量转换图片到webp,批量重命名文件,批量缩小webp大小,从flask/quart迁移到go等。

使用方法详见注释。

About

A python-based questionnaire server to get user's classification of images.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published