Staskaer / nonebot_plugin_RealESRGAN

基于nonebot的超分辨率重建
BSD 3-Clause "New" or "Revised" License
33 stars 3 forks source link

没有返回 #8

Closed KomoriDev closed 1 year ago

KomoriDev commented 1 year ago

没有返回图片或报错 image

init.py

from .utils import *
from nonebot.adapters.onebot.v11 import Message, MessageEvent, MessageSegment, Bot, Event
from service.gocqhttp_guild_patch import Message, GuildMessageEvent, MessageSegment, Bot, Event
from nonebot.params import T_State, CommandArg
from nonebot.plugin import on_command
from nonebot.adapters.onebot.v11.helpers import HandleCancellation
from json import loads
from nonebot import get_driver

try:
    api = loads(get_driver().config.json())["realesrgan_api"]
except:
    api = 'https://hf.space/embed/mute23/linxi_resolutionRatio/api/predict/'

real_esrgan = on_command(
    "重建", aliases={"real-esrgan", "超分辨率重建", "图片重建", "real_esrgan", "图像重建"}, priority=30
)

@real_esrgan.handle()
async def real_esrgan_handle_first(
    bot: Bot,
    event: MessageEvent | GuildMessageEvent,
    state: T_State,
    args: Message = CommandArg(),
):
    state['id'] = event.get_user_id()
    for seg in args:
        if seg.type == "text":
            state["mode"] = seg.data["text"].strip()
        if seg.type == "image":
            state['img'] = event.message['image']
            break

@real_esrgan.got("mode", prompt="请提供重建模式(二次元:anime,其他:base),模式不绝对,可以任意选", parameterless=[HandleCancellation("已取消")])
async def real_esrgan_get_mode(event: MessageEvent | GuildMessageEvent, state: T_State):
    mode = str(state["mode"]).strip()
    if mode not in ["anime", "base"]:
        await real_esrgan.reject('"base" | "anime", 二选一')

@real_esrgan.got("img", prompt="请上传需要超分辨率重建的图片", parameterless=[HandleCancellation("已取消")])
async def real_esrgan_handle_img(event: MessageEvent | GuildMessageEvent    , state: T_State):
    # 先拿到需要转换的图
    for seg in state["img"]:
        if seg.type == "image":
            img = await get_img(seg.data["url"])
            break
    else:
        await real_esrgan.finish(Message(f"[CQ:at,qq={state['id']}]不是图捏"))
    # 下面来处理图片
    try:
        json_data = img_encode_to_json(img, state['mode'])  # 先获取图片并进行编码
        if json_data is None:
            await real_esrgan.finish(Message(f"[CQ:at,qq={state['id']}]服务器无法接收到这张图捏,要不重试试试?"))
        result = await get_result(json_data, api=api)  # 然后进行超分辨率重建
        if result is None:
            await real_esrgan.finish(Message(f"[CQ:at,qq={state['id']}]这张图没能被正确解析,可能网络连接失败或者是由于远程服务器免费额度耗尽,如果是后者建议联系管理员使用自建仓库(免费)"))
        img = img_decode_from_json(result)  # 获取重建后图片并进行解码发送
        await real_esrgan.finish(MessageSegment.image(img))
    except Exception as e:
        ...
        # print('错误类型是', e.__class__.__name__)
        # print('错误明细是', e)

utils.py

from json import loads
from base64 import b64encode, b64decode
import aiohttp

######### 实现对图片的base64编码和从返回数据中解析出原始图片 #########

def img_encode_to_json(img: bytes, mode="base") -> dict:
    '''
    对二进制格式的图片进行base64编码,并组织成json格式返回,用于request请求
    Args:
        img (bytes): 二进制格式图片
    Returns:
        dict: 返回的json数据
    '''
    base64_data = b64encode(img)
    base64_data = str(base64_data, 'utf-8')
    return {
        'fn_index': 0,
        'data': [
            'data:image/jpeg;base64,{}'.format(base64_data),
            f'{mode}',
        ]
    }

def img_decode_from_json(response_str: str) -> bytes:
    '''
    将返回的json解析处img的base64再解码返回
    Args:
        response_str (str): 字符串格式的json
    Returns:
        bytes: img的二进制格式
    '''
    result = loads(response_str)
    img_base64 = result['data'][0].split("base64,")[1]
    return b64decode(img_base64)

######### 网络请求部分 #########

async def get_img(img_url: str) -> bytes:
    '''
    将收到的图片下载下来,并转换成二进制格式
    Args:
        img_url (str): 图片url地址
    Returns:
        bytes: 二进制格式的图片
    '''
    async with aiohttp.ClientSession() as session:
        async with session.get(img_url) as resp:
            result = await resp.content.read()
    if not result:
        return None
    return result

async def get_result(json_data: dict) -> str:
    '''
    来构造请求并获取返回的重建后的图像
    Args:
        json_data (dict): 对图片编码后的数据
    Returns:
        str: 返回的json格式数据
    '''
    headers = {
        'authority': 'hf.space',
        'accept': '*/*',
        'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'cache-control': 'no-cache',
        # Already added when you pass json=
        # 'content-type': 'application/json',
        'dnt': '1',
        'origin': 'https://hf.space',
        'pragma': 'no-cache',
        'referer': 'https://hf.space/embed/mute23/linxi_resolutionRatio/+?__theme=light',
        'sec-ch-ua': '"Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'sec-gpc': '1',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',
    }
    try:
        async with aiohttp.ClientSession() as session:
            async with session.post('https://hf.space/embed/mute23/linxi_resolutionRatio/api/predict/', headers=headers, json=json_data, timeout=120) as resp:
                result = await resp.text()
        if not result:
            return None
        return result
    except:
        return None

自建的api,可以在仓库中运行,但是在QQ中却没有返回。日志也只显示了接受消息


01-25 14:36:03 [SUCCESS] nonebot | OneBot V11 2871703871 | [message.group.normal]: Message -1242437820 from 2740324073@[群:413820772] ".重建 anime"
01-25 14:36:03 [INFO] nonebot | Event will be handled by Matcher(type='message', module=service.ayaka.adapters.nb2ob11)
01-25 14:36:03 [INFO] nonebot | Matcher(type='message', module=service.ayaka.adapters.nb2ob11) running complete
01-25 14:36:03 [INFO] nonebot | Event will be handled by Matcher(type='message', module=plugins.pixiv.Resolution_Ratio)
01-25 14:36:03 [INFO] nonebot_plugin_gocqhttp | [2871703871] 发送群 林汐咖啡屋<$ÿĀ>(413820772) 的消息: [{"type":  ... (-1024010286)
01-25 14:36:03 [INFO] nonebot | Matcher(type='message', module=plugins.pixiv.Resolution_Ratio) running complete
[CQ:image,file=4d89fd20ac9d1e95ed42fb94138e0f9b.image,subType=1,url=https://gchat.qpic.cn/gchatpic_new/2309512001/549774919-3009018648-4D89FD20AC9D1E95ED42FB94138E0F9B/0?term=3&amp;is_origin=0] (541433117)
01-25 14:36:04 [SUCCESS] nonebot | OneBot V11 2871703871 | [message.group.normal]: Message 541433117 from 2309512001@[群:549774919] "[CQ:image,file=4d89fd20ac9d1e95ed42fb94138e0f9b.image,subType=1,url=https://gchat.qpic.cn/gchatpic_new/2309512001/549774919-3009018648-4D89FD20AC9D1E95ED42FB94138E0F9B/0?term=3&amp;is_origin=0]"
01-25 14:36:04 [INFO] nonebot | Event message.group.normal is ignored
01-25 14:36:09 [INFO] nonebot_plugin_gocqhttp | [2871703871] 收到群 林汐咖啡屋<$ÿĀ>(413820772) 内 逐梦(2740324073) 的 消息: [CQ:image,file=2003b5f703263766a12aedbc1768590e.image,subType=0,url=https://gchat.qpic.cn/gchatpic_new/2740324073/3903820772-3166440416-2003B5F703263766A12AEDBC1768590E/0?term=3&amp;is_origin=0] (1543472744)
01-25 14:36:09 [SUCCESS] nonebot | OneBot V11 2871703871 | [message.group.normal]: Message 1543472744 from 2740324073@[ 群:413820772] "[CQ:image,file=2003b5f703263766a12aedbc1768590e.image,subType=0,url=https://gchat.qpic.cn/gchatpic_new/2740324073/3903820772-3166440416-2003B5F703263766A12AEDBC1768590E/0?term=3&amp;is_origin=0]"
01-25 14:36:09 [INFO] nonebot | Event will be handled by Matcher(type='message', module=plugins.pixiv.Resolution_Ratio)
01-25 14:36:12 [INFO] nonebot | Matcher(type='message', module=plugins.pixiv.Resolution_Ratio) running complete
Staskaer commented 1 year ago

@real_esrgan.got("img", prompt="请上传需要超分辨率重建的图片", parameterless=[HandleCancellation("已取消")])
async def real_esrgan_handle_img(event: MessageEvent | GuildMessageEvent    , state: T_State):
    # 先拿到需要转换的图
    for seg in state["img"]:
        if seg.type == "image":
            img = await get_img(seg.data["url"])
            break
    else:
        await real_esrgan.finish(Message(f"[CQ:at,qq={state['id']}]不是图捏"))
    # 下面来处理图片
    try:
        json_data = img_encode_to_json(img, state['mode'])  # 先获取图片并进行编码
        if json_data is None:
            await real_esrgan.finish(Message(f"[CQ:at,qq={state['id']}]服务器无法接收到这张图捏,要不重试试试?"))
        result = await get_result(json_data, api=api)  # 然后进行超分辨率重建
        if result is None:
            await real_esrgan.finish(Message(f"[CQ:at,qq={state['id']}]这张图没能被正确解析,可能网络连接失败或者是由于远程服务器免费额度耗尽,如果是后者建议联系管理员使用自建仓库(免费)"))
        img = img_decode_from_json(result)  # 获取重建后图片并进行解码发送
        await real_esrgan.finish(MessageSegment.image(img))
    except Exception as e:
        ...
        # 把下面这里解除注释
        print('错误类型是', e.__class__.__name__)
        print('错误明细是', e)
KomoriDev commented 1 year ago

删掉 try... except 后报错

01-26 20:37:41 [ERROR] nonebot | Running Matcher(type='message', module=plugins.pixiv.Resolution_Ratio) failed.
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\multiprocessing\spawn.py", line 116, in spawn_main
    exitcode = _main(fd, parent_sentinel)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\multiprocessing\spawn.py", line 129, in _main
    return self._bootstrap(parent_sentinel)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 315, in _bootstrap
    self.run()
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\Administrator\AppData\Local\pypoetry\Cache\virtualenvs\linxi-doM17b9W-py3.10\lib\site-packages\nonebot_plugin_reboot\reloader.py", line 27, in _run
    _nb_run(*args, **kwargs)
  File "C:\Users\Administrator\AppData\Local\pypoetry\Cache\virtualenvs\linxi-doM17b9W-py3.10\lib\site-packages\nonebot\__init__.py", line 273, in run
    get_driver().run(*args, **kwargs)
  File "C:\Users\Administrator\AppData\Local\pypoetry\Cache\virtualenvs\linxi-doM17b9W-py3.10\lib\site-packages\nonebot\drivers\fastapi.py", line 172, in run
    uvicorn.run(
  File "C:\Users\Administrator\AppData\Local\pypoetry\Cache\virtualenvs\linxi-doM17b9W-py3.10\lib\site-packages\uvicorn\main.py", line 569, in run
    server.run()
  File "C:\Users\Administrator\AppData\Local\pypoetry\Cache\virtualenvs\linxi-doM17b9W-py3.10\lib\site-packages\uvicorn\server.py", line 60, in run
    return asyncio.run(self.serve(sockets=sockets))
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\asyncio\runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 633, in run_until_complete
    self.run_forever()
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\asyncio\windows_events.py", line 321, in run_forever
    super().run_forever()
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 600, in run_forever
    self._run_once()
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 1896, in _run_once
    handle._run()
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\asyncio\events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "C:\Users\Administrator\AppData\Local\pypoetry\Cache\virtualenvs\linxi-doM17b9W-py3.10\lib\site-packages\nonebot\message.py", line 142, in _check_matcher
    await _run_matcher(Matcher, bot, event, state, stack, dependency_cache)
> File "C:\Users\Administrator\AppData\Local\pypoetry\Cache\virtualenvs\linxi-doM17b9W-py3.10\lib\site-packages\nonebot\message.py", line 188, in _run_matcher
    await matcher.run(bot, event, state, stack, dependency_cache)
  File "C:\Users\Administrator\AppData\Local\pypoetry\Cache\virtualenvs\linxi-doM17b9W-py3.10\lib\site-packages\nonebot\internal\matcher\matcher.py", line 727, in run
    await self.simple_run(bot, event, state, stack, dependency_cache)
  File "C:\Users\Administrator\AppData\Local\pypoetry\Cache\virtualenvs\linxi-doM17b9W-py3.10\lib\site-packages\nonebot\internal\matcher\matcher.py", line 702, in simple_run
    await handler(
  File "C:\Users\Administrator\AppData\Local\pypoetry\Cache\virtualenvs\linxi-doM17b9W-py3.10\lib\site-packages\nonebot\dependencies\__init__.py", line 108, in __call__
    return await cast(Callable[..., Awaitable[R]], self.call)(**values)
  File "C:\linxi_bot\plugins\pixiv\Resolution_Ratio\__init__.py", line 57, in real_esrgan_handle_img
    result = await get_result(json_data, api=api)  # 然后进行超分辨率重建
TypeError: get_result() got an unexpected keyword argument 'api'
KomoriDev commented 1 year ago

找到问题了,是我的utils.py出现了问题 我写的是:

async def get_result(json_data: dict) -> str:

按照源码改成

async def get_result(json_data: dict, *, api) -> str:

成功,已经有返回了,谢谢指点