用户可以利用api自己上传图像并指定分类,也可以从服务器的图像中查看图片,并指定分类。
你需要安装pillow
,numba
,imagehash
,quart/flask
, gevent
(如果使用flask
)等包以确保程序运行。
pip install -r requirements.txt
由于整合了setu-class,你需要编译安装setu-class-cpp库,该库要求您已经安装了libtorch
。然后,请将该仓库的ero.pt
和nor.pt
复制到本项目编译出的可执行文件旁。
另外,您还需要部署一个simple-storage,命令行参数中需要填写其apiurl
与authkey
。
接下来安装libwebp-dev
,并在使用前运行
go mod tidy
首先克隆本仓库
git clone --depth=1 https://github.com/fumiama/image-classification-questionnaire-server.git
- 如果你是
ubuntu
用户,由于该系统绑定80
端口需要root
权限,因此需要添加可选参数userid
以在绑定端口后降权运行。 - 密码必须为两个汉字,在运行后密码将在命令行被隐藏,但不会清除命令历史记录,请手动清除。
Usage: <listen_addr> <apiurl> <password> <authkey> <dbfile> (userid) &
注意:
- 如果添加末尾的
&
,程序将会以daemon
运行。 userid
为可选项。如果设置,程序将会在绑定端口后切换到该uid
处理请求。Windows
下使用不支持userid
选项。dbfile
位置任意。
- 如果使用
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
- 如果你是
ubuntu
用户,由于该系统绑定80
端口需要root
权限,因此需要添加可选参数server_uid
以在绑定端口后降权运行。 - 密码文件
pwd_path
必须为以UTF16BE
编码存储的两个汉字(包括文件头0xfeff
),总长6
字节。
注意:使用一段时间后可能会无响应,目前尚未解决,只能通过daemon.sh
监控进程是否退出,如果退出则重新拉起。
./server.py [-d] <user_dir> <image_dir> <pwd_path> (server_uid)
其中:
-d
为可选项,如果设置,程序将会以daemon
运行。server_uid
为可选项。如果设置,程序将会在绑定端口后切换到该uid
处理请求。
./server_quart/flask.py <user_dir> <image_dir> <pwd_path> (server_uid) 2>&1 > ./log.txt &
其中:
- 如果添加末尾的
&
,程序将会以daemon
运行。 server_uid
为可选项。如果设置,程序将会在绑定端口后切换到该uid
处理请求。
注意:
- 服务端图片扩展名只接受
.webp
,客户端上传时任意。如需其它格式请自行修改代码。 - 图片的唯一标识使用了该图片
dhash
值的base16384
编码的前五个汉字。
对应执行文件为server.go
,该版本的class只能为0~7的整数。
-
格式: http://[server_domain]/
-
说明: 直接通过简易网页访问服务。
-
格式: http://[server_domain]/signup?key=1234567890
-
返回:
- 成功
{"stat":"success", "id":"%XX%XX%XX%XX%XX%XX"}
- 密码错误
{"stat":"wrong", "id":"null"}
- 处理错误
400 BAD REQUEST
- 说明:
- 返回转义的两个
utf-8
编码的汉字,代表下面用到的uuid
key
后跟10位整数,表示密码与当前秒数异或的结果,与服务端相差10秒内有效
-
格式: http://[server_domain]/vote?uuid=用户&img=投票的图片&class=n
-
返回:
- 成功
{"stat":"success"}
- 图片名格式非法
{"stat":"invimg"}
- 用户名格式非法
{"stat":"invid"}
- 找不到uuid/img/class字段
400 BAD REQUEST
- class非法
{"stat":"invclass"}
- 说明:
uuid
字段容纳两(数量不可增减)个utf-8
编码的汉字,表示投票用户。img
字段容纳五个(数量不可增减)utf-8
编码的汉字,唯一标识了这张图片。class
字段class只能为0~7的整数,代表该图片所属标签。
-
格式: http://[server_domain]/img?path=某一张图片
-
返回:
- 成功
图片数据
- 无此图片
{"stat":"nosuchimg"}
- 图片名格式非法
{"stat":"invimg"}
- 说明:
目标的图片
是五个(数量不可增减)utf-8
编码的汉字,唯一标识了这张图片。
-
格式:
HTTP POST
到http://[server_domain]/upload?uuid=用户 -
返回:
- 成功
{"stat":"success","result":[{"stat": "success","img": "%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX"}]}
- 相似或相同图片存在
{"stat":"success","result":[{"stat":"exist","img":"%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX"}]}
- 空请求体
{"stat":"emptybody"}
- 找不到此用户
{"stat":"noid"}
- 解析dhash错误
{"stat":"success","result":[{"stat":"notanimg","img":""}]}
- 不是图片
{"stat":"success","result":[{"stat":"notanimg","img":""}]}
- io错误
{"stat":"success","result":[{"stat":"ioerr","img":""}]}
- 图片转码错误
{"stat":"success","result":[{"stat":"encerr","img":""}]}
- 说明: 必须为
webp
、jpg
、png
或gif
格式。使用wget
时,可使用如下命令。
wget --post-file=image.webp http://[server_domain]/upload?uuid=用户
该API无法上传合计大于64M的文件,可以更改ParseMultipartForm入参以提高上限
- 格式:
HTTP POST
到http://[server_domain]/upform?uuid=用户
该格式支持批量上传。
- 成功 返回时,会将全部结果统一送回。
{"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"}
- io错误
{"stat":"success","result":[{"stat":"ioerr","img":""}]}
- 说明: 必须为
webp
、jpg
、png
或gif
格式。
- 格式: http://[server_domain]/pickdl?uuid=用户
- 返回:
- 成功
图片数据
- 无更多图片
{"stat":"nomoreimg"}
- 无此用户
{"stat":"noid"}
- 用户名格式非法
400 BAD REQUEST
- 说明:
用户
是两个(数量不可增减)utf-8
编码的汉字,唯一标识了某个用户。
- 格式: http://[server_domain]/pick?uuid=用户
- 返回:
- 成功
{"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"}
- 无更多图片
{"stat":"nomoreimg"}
- 无此用户
{"stat":"noid"}
- 用户名格式非法
400 BAD REQUEST
- 说明:
用户
是两个(数量不可增减)utf-8
编码的汉字,唯一标识了某个用户。- 返回的图片名经过了转义。
参数详见setu-class
-
格式: http://[server_domain]/dhash?pidp=pid_pn
-
返回:
- 成功
{"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"}
- 失败
各种状态码,附带简短说明
对应执行文件为server.py
-
格式: http://[server_domain]/index.html
-
说明: 直接通过简易网页访问服务。
-
格式: http://[server_domain]/signup?1234567890
-
返回: 成功(succ),密码错误(null),处理错误(erro)
-
说明:
- 返回
utf-8
编码的两个汉字,代表下面用到的uuid
- 后跟10位整数,表示密码与当前秒数异或的结果,与服务端相差10秒内有效
-
格式: http://[server_domain]/vote?uuid=用户&img=投票的图片&class=n
-
返回: 成功(succ),错误(erro)
-
说明:
uuid
字段容纳两(数量不可增减)个utf-8
编码的汉字,表示投票用户。img
字段容纳五个(数量不可增减)utf-8
编码的汉字,唯一标识了这张图片。class
字段容纳最多184个ASCII
编码,代表该图片所属标签。
-
格式: http://[server_domain]/目标的图片
-
返回: 成功(图片数据),空(null),错误(erro)
-
说明:
目标的图片
是五个(数量不可增减)utf-8
编码的汉字,唯一标识了这张图片。
-
格式:
HTTP POST
到http://[server_domain]/upload?uuid=用户 -
返回: 成功(succ),错误(erro),图片相似/无此用户(null)
-
说明: 必须为
webp
、jpg
、png
或gif
格式。使用wget
时,可使用如下命令。
wget --post-file=image.webp http://[server_domain]/upload?uuid=用户
-
格式: http://[server_domain]/pickdl?用户
-
返回: 成功(图片数据),空(null),错误(erro)
-
说明:
用户
是两个(数量不可增减)utf-8
编码的汉字,唯一标识了某个用户。
-
格式: http://[server_domain]/pick?用户
-
返回: 成功(图片名),空(null),错误(erro)
-
说明:
用户
是两个(数量不可增减)utf-8
编码的汉字,唯一标识了某个用户。- 返回的图片名经过了转义。
对应执行文件为server_quart.py
-
格式: http://[server_domain]/index.html
-
说明: 直接通过简易网页访问服务。
-
格式: http://[server_domain]/signup?key=1234567890
-
返回:
- 成功
{"stat":"success", "id":"%XX%XX%XX%XX%XX%XX"}
- 密码错误
{"stat":"wrong", "id":"null"}
- 处理错误
{"stat":"error", "id":"null"}
- 说明:
- 返回转义的两个
utf-8
编码的汉字,代表下面用到的uuid
key
后跟10位整数,表示密码与当前秒数异或的结果,与服务端相差10秒内有效
-
格式: http://[server_domain]/vote?uuid=用户&img=投票的图片&class=n
-
返回:
- 成功
{"stat":"success"}
- 图片名格式非法
{"stat":"invimg"}
- 用户名格式非法
{"stat":"invid"}
- 找不到此用户
{"stat":"noid"}
- 说明:
uuid
字段容纳两(数量不可增减)个utf-8
编码的汉字,表示投票用户。img
字段容纳五个(数量不可增减)utf-8
编码的汉字,唯一标识了这张图片。class
字段容纳最多184个ASCII
编码,代表该图片所属标签。
-
格式: http://[server_domain]/img?path=某一张图片
-
返回:
- 成功
图片数据
- 读图片错误
{"stat":"readimgerr"}
- 无此图片
{"stat":"nosuchimg"}
- 图片名格式非法
{"stat":"invimg"}
- 说明:
目标的图片
是五个(数量不可增减)utf-8
编码的汉字,唯一标识了这张图片。
Quart版目前无法上传大于20M的图片
-
格式:
HTTP POST
到http://[server_domain]/upload?uuid=用户 -
返回:
- 成功
{"stat":"success", "img":"%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX"}
- 相似或相同图片存在
{"stat":"exist", "img":"%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX%XX"}
- 用户名格式非法
{"stat":"invid"}
- 找不到此用户
{"stat":"noid"}
- 接收图片错误
{"stat":"recverr"}
- 不是图片
{"stat": "notanimg"}
- 说明: 必须为
webp
、jpg
、png
或gif
格式。使用wget
时,可使用如下命令。
wget --post-file=image.webp http://[server_domain]/upload?uuid=用户
该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"}]}
其中,列表的每一项都遵循如下格式
- 成功
{"name":"xxx","stat":"success"}
- 相似或相同图片存在
{"name":"xxx","stat":"exist"}
- 用户名格式非法
{"name":"xxx","stat":"invid"}
- 找不到此用户
{"name":"xxx","stat":"noid"}
- 接收图片错误
{"stat":"recverr"}
- 不是图片
{"stat": "notanimg"}
- 说明: 必须为
webp
、jpg
、png
或gif
格式。
-
格式: http://[server_domain]/pickdl?uuid=用户
-
返回:
- 成功
图片数据
- 读图片错误
{"stat":"readimgerr"}
- 无更多图片
{"stat":"nomoreimg"}
- 无此用户
{"stat":"noid"}
- 用户名格式非法
{"stat":"invid"}
- 说明:
用户
是两个(数量不可增减)utf-8
编码的汉字,唯一标识了某个用户。
-
格式: http://[server_domain]/pick?uuid=用户
-
返回:
- 成功
{"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"}
- 读图片错误
{"stat":"readimgerr"}
- 无更多图片
{"stat":"nomoreimg"}
- 无此用户
{"stat":"noid"}
- 用户名格式非法
{"stat":"invid"}
- 说明:
用户
是两个(数量不可增减)utf-8
编码的汉字,唯一标识了某个用户。- 返回的图片名经过了转义。
一些实用的小工具放在了tools
文件夹,包括批量上传图片,批量转换图片到webp
,批量重命名文件,批量缩小webp
大小,从flask/quart迁移到go等。
使用方法详见注释。