【NovelAI】在QQ群中部署AI画图机器人
目錄
一、NovelAI?
二、UIautomation和pywin32
三、代碼?
1、AI畫(huà)圖相關(guān)
?2、QQ群消息抓取相關(guān)
四、代碼效果?
五、后記?
一、NovelAI?
NovelAI是一個(gè)用來(lái)畫(huà)二次元圖片的開(kāi)源算法,部署方式見(jiàn)? b站鏈接
二、UIautomation和pywin32
UIautomation和pywin32是python的庫(kù),主要用于窗口句柄的抓取和操作,本代碼中用于接收、發(fā)送QQ群消息?
三、代碼?
1、AI畫(huà)圖相關(guān)
通過(guò)使用NovelAI代碼包里的txt2img.py文件,實(shí)現(xiàn)從文字到圖片的轉(zhuǎn)化:
def txt2img(prompt: str, negative_prompt: str, prompt_style: str, prompt_style2: str, steps: int, sampler_index: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, height: int, width: int, enable_hr: bool, scale_latent: bool, denoising_strength: float, *args):p = StableDiffusionProcessingTxt2Img(sd_model=shared.sd_model,outpath_samples=opts.outdir_samples or opts.outdir_txt2img_samples,outpath_grids=opts.outdir_grids or opts.outdir_txt2img_grids,prompt=prompt,styles=[prompt_style, prompt_style2],negative_prompt=negative_prompt,seed=seed,subseed=subseed,subseed_strength=subseed_strength,seed_resize_from_h=seed_resize_from_h,seed_resize_from_w=seed_resize_from_w,seed_enable_extras=seed_enable_extras,sampler_index=sampler_index,batch_size=batch_size,n_iter=n_iter,steps=steps,cfg_scale=cfg_scale,width=width,height=height,restore_faces=restore_faces,tiling=tiling,enable_hr=enable_hr,scale_latent=scale_latent if enable_hr else None,denoising_strength=denoising_strength if enable_hr else None,)if cmd_opts.enable_console_prompts:print(f"\ntxt2img: {prompt}", file=shared.progress_print_out)processed = modules.scripts.scripts_txt2img.run(p, *args)if processed is None:processed = process_images(p)shared.total_tqdm.clear()generation_info_js = processed.js()if opts.samples_log_stdout:print(generation_info_js)if opts.do_not_show_images:processed.images = []return processed.images, generation_info_js, plaintext_to_html(processed.info)輸入對(duì)應(yīng)的參數(shù)后,圖像數(shù)據(jù)存儲(chǔ)在以下位置
txt2img[0][0].save(fullfn)#fullfn是路徑?2、QQ群消息抓取相關(guān)
接收方面
_get_all_hwnd(hwnd, mouse)用于遍歷QQ窗口下的所有控件,用于找到消息管理器窗口下的所有控件
def _get_all_hwnd(hwnd, mouse):if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd):hwnd_title.update({hwnd: win32gui.GetWindowText(hwnd)})textrefresh(delay)用于點(diǎn)擊消息管理器的刷新按鈕,以更新群消息
def textrefresh(delay):win32gui.EnumWindows(_get_all_hwnd, 0)for wnd in hwnd_title.items():# print(wnd)if wnd[1] == '消息管理器':breaklong_position = win32api.MAKELONG(810, 130)win32api.SendMessage(int(wnd[0]), win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, long_position)win32api.SendMessage(int(wnd[0]), win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, long_position)sleep(delay)?之后在一個(gè)while循環(huán)里不斷獲取最新的一條群消息,并用正則表達(dá)式提取指令,以用于后續(xù)操作
chat_window = auto.WindowControl(searchDepth=1, ClassName='TXGuiFoundation', Name='消息管理器') msg_list = chat_window.ListControl(Name='IEMsgView') #找到 list finalmsg = msg_list.GetLastChildControl() msg = finalmsg.Name # print(msg) obj = re.compile(r'.*?\((?P<QQnum>.*?)\)\d{1,}:\d{2}:\d{2}(?P<QQmsg>.*)', re.S) #可拿出 result = obj.findall(msg)需要注意的是“點(diǎn)擊刷新按鈕”和“獲取群消息”是兩個(gè)事件。
不同點(diǎn)是“點(diǎn)擊刷新按鈕”使用的是win32api,win32gui,win32con庫(kù),“獲取群消息”使用的是uiautomation庫(kù)。
相同點(diǎn)是這兩個(gè)操作都是針對(duì)“消息管理器”窗口的。
uiautomation庫(kù)和win32api,win32gui,win32con庫(kù)有很多共有的功能,兩者都是對(duì)控件進(jìn)行操作的庫(kù),博主在使用時(shí)有所取舍。
對(duì)于“點(diǎn)擊刷新按鈕”需求:uiautomation的點(diǎn)擊操作需要占用鼠標(biāo),很不方便,而win32庫(kù)里有后臺(tái)鼠標(biāo),因此用于實(shí)現(xiàn)“點(diǎn)擊刷新按鈕”的需求是合適的。
對(duì)于“獲取群消息”需求:win32庫(kù)需要遍歷所有子控件,博主認(rèn)為這會(huì)提高運(yùn)行時(shí)間,并且定位最后一條群消息還需要額外的篩選操作,而uiautomation里可以直接調(diào)用GetLastChildControl()方法得到最后一個(gè)子控件,而這個(gè)最后的子控件剛好是群內(nèi)最新的消息。
至此程序已經(jīng)完成了提取群消息里的指令的需求
發(fā)送方面
fs(fsgs, fsnr)用于向群聊天窗口發(fā)送文字信息
def fs(fsgs, fsnr):c.OpenClipboard()c.EmptyClipboard()c.SetClipboardData(b.CF_UNICODETEXT, fsnr)c.CloseClipboard()handle = a.FindWindow(None, fsgs)if handle != 0:a.SendMessage(handle, 770, 0, 0)a.SendMessage(handle, b.WM_KEYDOWN, b.VK_RETURN, 0)print('消息發(fā)送成功!')sendImage(name,imgpath)用于向群聊天窗口發(fā)送圖片
def sendImage(name,imgpath):im = Image.open(imgpath)im.save('1.bmp')aString = windll.user32.LoadImageW(0, r"1.bmp", win32con.IMAGE_BITMAP, 0, 0, win32con.LR_LOADFROMFILE)#print(aString)if aString != 0: ## 由于圖片編碼問(wèn)題 圖片載入失敗的話(huà) aString 就等于0w.OpenClipboard()w.EmptyClipboard()w.SetClipboardData(win32con.CF_BITMAP, aString)# 關(guān)閉剪貼板w.CloseClipboard()# 獲取qq窗口句柄handle = win32gui.FindWindow(None, name)if handle == 0:print('未找到窗口!')# 顯示窗口win32gui.ShowWindow(handle, win32con.SW_SHOW)# time.sleep(0.2)# 把剪切板內(nèi)容粘貼到qq窗口win32gui.SendMessage(handle, win32con.WM_PASTE, 0, 0)# time.sleep(0.2)# 按下后松開(kāi)回車(chē)鍵,發(fā)送消息win32gui.SendMessage(handle, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)win32gui.SendMessage(handle, win32con.WM_KEYUP, win32con.VK_RETURN, 0)至此程序已經(jīng)完成了向群里發(fā)送文字和圖片的需求
以上是主要的代碼,后面還需要設(shè)置條件判斷群友是不是@了機(jī)器人,以及@機(jī)器人后的指令該怎么使用 ,等等的細(xì)節(jié)這里省略(不難)
四、代碼效果?
五、后記?
反正也沒(méi)人看,權(quán)當(dāng)是個(gè)人學(xué)習(xí)記錄吧
僅供娛樂(lè),如有侵權(quán)請(qǐng)聯(lián)系我刪除?
總結(jié)
以上是生活随笔為你收集整理的【NovelAI】在QQ群中部署AI画图机器人的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 设计模式---------门面模式
- 下一篇: AI量化交易(一)——量化交易简介