| import math | |
| import os | |
| import sys | |
| import traceback | |
| import cv2 | |
| from PIL import Image | |
| import numpy as np | |
| lastx,lasty=None,None | |
| zoomOrigin = 0,0 | |
| zoomFactor = 1 | |
| midDragStart = None | |
| def display_mask_ui(image,mask,max_size,initPolys): | |
| global lastx,lasty,zoomOrigin,zoomFactor | |
| lastx,lasty=None,None | |
| zoomOrigin = 0,0 | |
| zoomFactor = 1 | |
| polys = initPolys | |
| def on_mouse(event, x, y, buttons, param): | |
| global lastx,lasty,zoomFactor,midDragStart,zoomOrigin | |
| lastx,lasty = (x+zoomOrigin[0])/zoomFactor,(y+zoomOrigin[1])/zoomFactor | |
| if event == cv2.EVENT_LBUTTONDOWN: | |
| polys[-1].append((lastx,lasty)) | |
| elif event == cv2.EVENT_RBUTTONDOWN: | |
| polys.append([]) | |
| elif event == cv2.EVENT_MBUTTONDOWN: | |
| midDragStart = zoomOrigin[0]+x,zoomOrigin[1]+y | |
| elif event == cv2.EVENT_MBUTTONUP: | |
| if midDragStart is not None: | |
| zoomOrigin = max(0,midDragStart[0]-x),max(0,midDragStart[1]-y) | |
| midDragStart = None | |
| elif event == cv2.EVENT_MOUSEMOVE: | |
| if midDragStart is not None: | |
| zoomOrigin = max(0,midDragStart[0]-x),max(0,midDragStart[1]-y) | |
| elif event == cv2.EVENT_MOUSEWHEEL: | |
| origZoom = zoomFactor | |
| if buttons > 0: | |
| zoomFactor *= 1.1 | |
| else: | |
| zoomFactor *= 0.9 | |
| zoomFactor = max(1,zoomFactor) | |
| zoomOrigin = max(0,int(zoomOrigin[0]+ (max_size*0.25*(zoomFactor-origZoom)))) , max(0,int(zoomOrigin[1] + (max_size*0.25*(zoomFactor-origZoom)))) | |
| opencvImage = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) | |
| if mask is None: | |
| opencvMask = cv2.cvtColor( np.array(opencvImage) , cv2.COLOR_BGR2GRAY) | |
| else: | |
| opencvMask = np.array(mask) | |
| maxdim = max(opencvImage.shape[1],opencvImage.shape[0]) | |
| factor = max_size/maxdim | |
| cv2.namedWindow('MaskingWindow', cv2.WINDOW_AUTOSIZE) | |
| cv2.setWindowProperty('MaskingWindow', cv2.WND_PROP_TOPMOST, 1) | |
| cv2.setMouseCallback('MaskingWindow', on_mouse) | |
| font = cv2.FONT_HERSHEY_SIMPLEX | |
| srcImage = opencvImage.copy() | |
| combinedImage = opencvImage.copy() | |
| interp = cv2.INTER_CUBIC | |
| if zoomFactor*factor < 0: | |
| interp = cv2.INTER_AREA | |
| zoomedSrc = cv2.resize(srcImage,(None,None),fx=zoomFactor*factor,fy=zoomFactor*factor,interpolation=interp) | |
| zoomedSrc = zoomedSrc[zoomOrigin[1]:zoomOrigin[1]+max_size,zoomOrigin[0]:zoomOrigin[0]+max_size,:] | |
| lastZoomFactor = zoomFactor | |
| lastZoomOrigin = zoomOrigin | |
| while 1: | |
| if lastZoomFactor != zoomFactor or lastZoomOrigin != zoomOrigin: | |
| interp = cv2.INTER_CUBIC | |
| if zoomFactor*factor < 0: | |
| interp = cv2.INTER_AREA | |
| zoomedSrc = cv2.resize(srcImage,(None,None),fx=zoomFactor*factor,fy=zoomFactor*factor,interpolation=interp) | |
| zoomedSrc = zoomedSrc[zoomOrigin[1]:zoomOrigin[1]+max_size,zoomOrigin[0]:zoomOrigin[0]+max_size,:] | |
| zoomedSrc = cv2.copyMakeBorder(zoomedSrc, 0, max_size-zoomedSrc.shape[0], 0, max_size-zoomedSrc.shape[1], cv2.BORDER_CONSTANT) | |
| lastZoomFactor = zoomFactor | |
| lastZoomOrigin = zoomOrigin | |
| foreground = np.zeros_like(zoomedSrc) | |
| for i,polyline in enumerate(polys): | |
| if len(polyline)>0: | |
| segs = polyline[::] | |
| active=False | |
| if len(polys[-1])>0 and i==len(polys)-1 and lastx is not None: | |
| segs = polyline+[(lastx,lasty)] | |
| active=True | |
| segs = np.array(segs) - np.array([(zoomOrigin[0]/zoomFactor,zoomOrigin[1]/zoomFactor)]) | |
| segs = (np.array([segs])*zoomFactor).astype(int) | |
| if active: | |
| cv2.fillPoly(foreground, (np.array(segs)) , ( 190, 107, 253), 0) | |
| else: | |
| cv2.fillPoly(foreground, (np.array(segs)) , (255, 255, 255), 0) | |
| if active: | |
| for x,y in segs[0]: | |
| cv2.circle(foreground, (int(x),int(y)), 5, (25,25,25), 3) | |
| cv2.circle(foreground, (int(x),int(y)), 5, (255,255,255), 2) | |
| foreground[foreground<1] = zoomedSrc[foreground<1] | |
| combinedImage = cv2.addWeighted(zoomedSrc, 0.5, foreground, 0.5, 0) | |
| helpText='Q=Save, C=Reset, LeftClick=Add new point to polygon, Rightclick=Close polygon, MouseWheel=Zoom, MidDrag=Pan' | |
| combinedImage = cv2.putText(combinedImage, helpText, (0,11), font, 0.4, (0,0,0), 2, cv2.LINE_AA) | |
| combinedImage = cv2.putText(combinedImage, helpText, (0,11), font, 0.4, (255,255,255), 1, cv2.LINE_AA) | |
| cv2.imshow('MaskingWindow',combinedImage) | |
| try: | |
| key = cv2.waitKey(1) | |
| if key == ord('q'): | |
| if len(polys[0])>0: | |
| newmask = np.zeros_like(cv2.cvtColor( opencvMask.astype('uint8') ,cv2.COLOR_GRAY2BGR) ) | |
| for i,polyline in enumerate(polys): | |
| if len(polyline)>0: | |
| segs = [(int(a/factor),int(b/factor)) for a,b in polyline] | |
| cv2.fillPoly(newmask, np.array([segs]), (255,255,255), 0) | |
| cv2.destroyWindow('MaskingWindow') | |
| return Image.fromarray( cv2.cvtColor( newmask, cv2.COLOR_BGR2GRAY) ),polys | |
| break | |
| if key == ord('c'): | |
| polys = [[]] | |
| except Exception as e: | |
| print(e) | |
| break | |
| cv2.destroyWindow('MaskingWindow') | |
| return mask,polys | |
| if __name__ == '__main__': | |
| img = Image.open('K:\\test2.png') | |
| oldmask = Image.new('L',img.size,(0,)) | |
| newmask,newPolys = display_mask_ui(img,oldmask,1024,[[]]) | |
| opencvImg = cv2.cvtColor( np.array(img) , cv2.COLOR_RGB2BGR) | |
| opencvMask = cv2.cvtColor( np.array(newmask) , cv2.COLOR_GRAY2BGR) | |
| combinedImage = cv2.addWeighted(opencvImg, 0.5, opencvMask, 0.5, 0) | |
| combinedImage = Image.fromarray( cv2.cvtColor( combinedImage , cv2.COLOR_BGR2RGB)) | |
| display_mask_ui(combinedImage,oldmask,1024,[[]]) | |
| exit() | |
| import modules.scripts as scripts | |
| import gradio as gr | |
| from modules.processing import Processed, process_images | |
| from modules.shared import opts, cmd_opts, state | |
| class Script(scripts.Script): | |
| def title(self): | |
| return "External Image Masking" | |
| def show(self, is_img2img): | |
| return is_img2img | |
| def ui(self, is_img2img): | |
| if not is_img2img: | |
| return None | |
| initialSize = 1024 | |
| try: | |
| import tkinter as tk | |
| root = tk.Tk() | |
| screen_width = int(root.winfo_screenwidth()) | |
| screen_height = int(root.winfo_screenheight()) | |
| print(screen_width,screen_height) | |
| initialSize = min(screen_width,screen_height)-50 | |
| print(initialSize) | |
| except Exception as e: | |
| print(e) | |
| max_size = gr.Slider(label="Masking preview size", minimum=512, maximum=initialSize*2, step=8, value=initialSize) | |
| with gr.Row(): | |
| ask_on_each_run = gr.Checkbox(label='Draw new mask on every run', value=False) | |
| non_contigious_split = gr.Checkbox(label='Process non-contigious masks separately', value=False) | |
| return [max_size,ask_on_each_run,non_contigious_split] | |
| def run(self, p, max_size, ask_on_each_run, non_contigious_split): | |
| if not hasattr(self,'lastImg'): | |
| self.lastImg = None | |
| if not hasattr(self,'lastMask'): | |
| self.lastMask = None | |
| if not hasattr(self,'lastPolys'): | |
| self.lastPolys = [[]] | |
| if ask_on_each_run or self.lastImg is None or self.lastImg != p.init_images[0]: | |
| if self.lastImg is None or self.lastImg != p.init_images[0]: | |
| self.lastPolys = [[]] | |
| p.image_mask,self.lastPolys = display_mask_ui(p.init_images[0],p.image_mask,max_size,self.lastPolys) | |
| self.lastImg = p.init_images[0] | |
| if p.image_mask is not None: | |
| self.lastMask = p.image_mask.copy() | |
| elif hasattr(self,'lastMask') and self.lastMask is not None: | |
| p.image_mask = self.lastMask.copy() | |
| if non_contigious_split: | |
| maskImgArr = np.array(p.image_mask) | |
| ret, markers = cv2.connectedComponents(maskImgArr) | |
| markerCount = markers.max() | |
| if markerCount > 1: | |
| tempimages = [] | |
| tempMasks = [] | |
| for maski in range(1,markerCount+1): | |
| print('maski',maski) | |
| maskSection = np.zeros_like(maskImgArr) | |
| maskSection[markers==maski] = 255 | |
| p.image_mask = Image.fromarray( maskSection.copy() ) | |
| proc = process_images(p) | |
| images = proc.images | |
| tempimages.append(np.array(images[0])) | |
| tempMasks.append(np.array(maskSection.copy())) | |
| finalImage = tempimages[0].copy() | |
| for outimg,outmask in zip(tempimages,tempMasks): | |
| resizeimg = cv2.resize(outimg, (finalImage.shape[0],finalImage.shape[1]) ) | |
| resizedMask = cv2.resize(outmask, (finalImage.shape[0],finalImage.shape[1]) ) | |
| finalImage[resizedMask==255] = resizeimg[resizedMask==255] | |
| images = [finalImage] | |
| else: | |
| proc = process_images(p) | |
| images = proc.images | |
| else: | |
| proc = process_images(p) | |
| images = proc.images | |
| proc.images = images | |
| return proc | |