Last active
March 4, 2021 04:52
-
-
Save tomatosoupcan/81a04fe30654b054561f7f4ba274bc90 to your computer and use it in GitHub Desktop.
Draw an image into Jackbox Games
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import mouse | |
import keyboard | |
import cv2 | |
import numpy as np | |
import urllib.request | |
import pyautogui | |
import time | |
import math | |
from matplotlib import pyplot as plt | |
from matplotlib.patches import Circle | |
import gc | |
import tkinter | |
import PIL.Image, PIL.ImageTk | |
import win32gui | |
import win32con | |
import subprocess | |
import os | |
from progressbar import AnimatedMarker, Bar, BouncingBar, Counter, ETA, \ | |
AdaptiveETA, FileTransferSpeed, FormatLabel, Percentage, \ | |
ProgressBar, ReverseBar, RotatingMarker, \ | |
SimpleProgress, Timer, UnknownLength | |
#def get_start(xx, yy): | |
#for pixel in image, find the next black pixel from the top that hasn't already been used and return it, if all pixels used, return 0 | |
# for x in range(0, maxx): | |
# for y in range(0, maxy): | |
# if resized[x, y] == 0: | |
# return [y, x] | |
# return 0 | |
def simplify(img): | |
available_colors = { | |
"red":[1,199,250], | |
"yellow":[26,173,247], | |
"green":[76,173,194], | |
"blue":[109,250,181], | |
"purple":[139,156,250] | |
} | |
available_colors_dark = { | |
"brown":[17,148,99], | |
"black":[0,0,0] | |
} | |
avacolor = list(available_colors.values()) | |
avacolord = list(available_colors_dark.values()) | |
img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) | |
indexline = 0 | |
for line in img: | |
indexpixel = 0 | |
for pixel in line: | |
shortest_distance = 99999 | |
destcolor = [0,0,255] | |
if pixel[2] > 128 and pixel[1] > 50: | |
for color in avacolor: | |
x = abs(color[0]-pixel[0]) | |
if x < shortest_distance: | |
shortest_distance = x | |
destcolor = color | |
elif pixel[1] <= 50: | |
destcolor = destcolor | |
else: | |
for color in avacolord: | |
x = color[0]-pixel[0] | |
y = color[1]-pixel[1] | |
z = color[2]-pixel[2] | |
dist = math.sqrt(x**2 + y**2 + z**2) | |
if dist < shortest_distance: | |
shortest_distance = dist | |
destcolor = color | |
img[indexline][indexpixel] = destcolor | |
indexpixel += 1 | |
indexline+=1 | |
img = cv2.cvtColor(img, cv2.COLOR_HSV2BGR) | |
return img | |
def pick_positions(): | |
global ul | |
global lr | |
print("Move Mouse to Upper Left Bounds and Press Enter") | |
keyboard.wait('enter') | |
ul = mouse.get_position() | |
print("Move Mouse to Lower Right Bounds and Press Enter") | |
keyboard.wait('enter') | |
lr = mouse.get_position() | |
ul=(ul[0]-13,ul[1]-14) | |
lr=(lr[0]-8,lr[1]-9) | |
def click_thru(): | |
global passit | |
print("Press Enter to continue, press P to repick positions:") | |
while True: | |
window.update() | |
hwnd = win32gui.FindWindow(None, "Outline Overlay") | |
lExStyle = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | |
lExStyle |= win32con.WS_EX_TRANSPARENT | win32con.WS_EX_LAYERED | |
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE , lExStyle ) | |
time.sleep(0.1) | |
if keyboard.is_pressed("enter"): | |
window.destroy() | |
passit = True | |
return | |
if keyboard.is_pressed("p"): | |
window.destroy() | |
pick_positions() | |
return | |
def display_window(resized2): | |
global window | |
window = tkinter.Tk() | |
window.title("Outline Overlay") | |
cv_img = cv2.cvtColor(resized2, cv2.COLOR_BGR2RGB) | |
height,width, no_channels = cv_img.shape | |
height = height-3 | |
width = width-3 | |
window.geometry('%dx%d+%d+%d' % (width, height, ul[0]+12, ul[1]+13)) | |
canvas = tkinter.Canvas(window, width = width, height = height) | |
canvas.pack() | |
photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) | |
canvas.create_image(0, 0, image=photo, anchor=tkinter.NW) | |
window.attributes('-alpha',0.3) | |
window.wm_attributes("-topmost", 1) | |
window.overrideredirect(1) | |
click_thru() | |
def get_start(x,y,resized): | |
if (resized == 0).sum() == 0: | |
return 0 | |
else: | |
tmp = resized[x,y] | |
r,c = np.nonzero(~resized) | |
min_idx = ((r - x)**2 + (c - y)**2).argmin() | |
return [c[min_idx], r[min_idx]] | |
def draw_image(simpl): | |
global redraw | |
while True: | |
xsize = lr[0]-ul[0] | |
ysize = lr[1]-ul[1] | |
resized = cv2.resize(img, (xsize, ysize), interpolation = cv2.INTER_AREA) | |
resized2 = cv2.resize(img2, (xsize, ysize), interpolation = cv2.INTER_AREA) | |
if simpl: | |
resized2 = simplify(resized2) | |
resized = cv2.Canny(resized,100,200) | |
#resized = cv2.ximgproc.thinning(resized,cv2.ximgproc.THINNING_GUOHALL) | |
resized = (255-resized) | |
resized = cv2.erode(resized,np.ones((5,5), np.uint8) , iterations=1) | |
resized = cv2.copyMakeBorder(resized, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=(255,255,255)) | |
resized = (255-resized) | |
resized = cv2.erode(resized,np.ones((2,2), np.uint8) , iterations=3) | |
resized = (255-resized) | |
cv2.imwrite("outlines.jpg", resized); | |
display_window(resized2) | |
if passit == True: | |
break | |
pyautogui.PAUSE = 0.005 | |
#intialize used pixels list | |
usedpixels=[] | |
#set relative cursor position | |
relcurx = 0 | |
relcury = 0 | |
#set absolute cursor location | |
mcurx = ul[0] | |
mcury = ul[1] | |
#set maximum x and y positions | |
maxx = resized.shape[0] | |
maxy = resized.shape[1] | |
returnedpoint = [0,0] | |
topcount = (resized == 0).sum() | |
#setup the progressbar | |
bar = ProgressBar(widgets=[Percentage(), Bar(), Timer()],maxval = topcount).start() | |
lastposx = 0 | |
posx = 0 | |
sleepswap = 0 | |
posy = 0 | |
while returnedpoint != 0: | |
returnedpoint = get_start(posy, posx,resized) | |
if returnedpoint == 0: | |
break | |
#provide myself a way out of mouse hell | |
if keyboard.is_pressed('escape'): | |
break | |
if keyboard.is_pressed('p'): | |
gambo = True | |
while gambo: | |
if keyboard.is_pressed('e'): | |
gambo = False | |
time.sleep(0.2) | |
#store off the current first black pixel | |
posx = returnedpoint[0] | |
posy = returnedpoint[1] | |
resized[posy,posx] = 1 | |
usedpixels=[(posy,posx)] | |
#move mouse to the start | |
mouse.move(mcurx+posx, mcury+posy, absolute = True, duration = 0) | |
#give the eventual downclick some breathing room | |
pyautogui.mouseDown(); | |
lastposx = posx | |
#latchon from the start position, latch will turn off when we can't find any other pixels to jump to | |
loopon = 0 | |
xdir = 0 | |
ydir = 0 | |
usedpixels = [(posy,posx)] | |
while loopon == 0: | |
#provide myself a way out of mouse hell | |
if keyboard.is_pressed('escape'): | |
break | |
#move mouse on each loop | |
mouse.move(mcurx+posx, mcury+posy, absolute = True, duration = 0) | |
for x in range(loopcount): | |
#for x in range(40000): | |
yyy = 0 | |
if xdir == 0 and ydir == 0: | |
if resized[posy, posx + 1] == 0: | |
#print("right") | |
posy = posy | |
posx = posx + 1 | |
xdir = 0 | |
elif resized[posy + 1, posx] == 0: | |
#print("down") | |
posx = posx | |
posy = posy + 1 | |
ydir = 0 | |
elif resized[posy + 1, posx + 1] == 0: | |
#print("downright") | |
posy = posy + 1 | |
posx = posx + 1 | |
ydir = 0 | |
xdir = 0 | |
elif resized[posy + 1, posx - 1] == 0: | |
#print("downleft") | |
posx = posx - 1 | |
posy = posy + 1 | |
ydir = 0 | |
xdir = 1 | |
elif resized[posy - 1, posx + 1] == 0: | |
#print("upright") | |
posx = posx + 1 | |
posy = posy - 1 | |
ydir = 1 | |
xdir = 0 | |
elif resized[posy, posx - 1] == 0: | |
#print("left") | |
posx = posx - 1 | |
posy = posy | |
xdir = 1 | |
elif resized[posy - 1, posx] == 0: | |
#print("up") | |
posx = posx | |
posy = posy - 1 | |
ydir = 1 | |
elif resized[posy - 1, posx - 1] == 0: | |
#print("upleft") | |
posx = posx - 1 | |
posy = posy - 1 | |
ydir = 1 | |
xdir = 1 | |
else: | |
#print("break") | |
loopon = 1 | |
break | |
elif xdir == 1 and ydir == 0: | |
if resized[posy, posx - 1] == 0: | |
#print("left") | |
posx = posx - 1 | |
posy = posy | |
xdir = 1 | |
elif resized[posy + 1, posx] == 0: | |
#print("down") | |
posx = posx | |
posy = posy + 1 | |
ydir = 0 | |
elif resized[posy + 1, posx - 1] == 0: | |
#print("downleft") | |
posx = posx - 1 | |
posy = posy + 1 | |
ydir = 0 | |
xdir = 1 | |
elif resized[posy, posx + 1] == 0: | |
#print("right") | |
posy = posy | |
posx = posx + 1 | |
xdir = 0 | |
elif resized[posy - 1, posx] == 0: | |
#print("up") | |
posx = posx | |
posy = posy - 1 | |
ydir = 1 | |
elif resized[posy + 1, posx + 1] == 0: | |
#print("downright") | |
posy = posy + 1 | |
posx = posx + 1 | |
ydir = 0 | |
xdir = 0 | |
elif resized[posy - 1, posx - 1] == 0: | |
#print("upleft") | |
posx = posx - 1 | |
posy = posy - 1 | |
ydir = 1 | |
xdir = 1 | |
elif resized[posy - 1, posx + 1] == 0: | |
#print("upright") | |
posx = posx + 1 | |
posy = posy - 1 | |
ydir = 1 | |
xdir = 0 | |
else: | |
#print("break") | |
loopon = 1 | |
break | |
elif xdir == 0 and ydir == 1: | |
if resized[posy, posx + 1] == 0: | |
#print("right") | |
posy = posy | |
posx = posx + 1 | |
xdir = 0 | |
elif resized[posy - 1, posx] == 0: | |
#print("up") | |
posx = posx | |
posy = posy - 1 | |
ydir = 1 | |
elif resized[posy - 1, posx + 1] == 0: | |
#print("upright") | |
posx = posx + 1 | |
posy = posy - 1 | |
ydir = 1 | |
xdir = 0 | |
elif resized[posy + 1, posx] == 0: | |
#print("down") | |
posx = posx | |
posy = posy + 1 | |
ydir = 0 | |
elif resized[posy, posx - 1] == 0: | |
#print("left") | |
posx = posx - 1 | |
posy = posy | |
xdir = 1 | |
elif resized[posy + 1, posx + 1] == 0: | |
#print("downright") | |
posy = posy + 1 | |
posx = posx + 1 | |
ydir = 0 | |
xdir = 0 | |
elif resized[posy - 1, posx - 1] == 0: | |
#print("upleft") | |
posx = posx - 1 | |
posy = posy - 1 | |
ydir = 1 | |
xdir = 1 | |
elif resized[posy + 1, posx - 1] == 0: | |
#print("downleft") | |
posx = posx - 1 | |
posy = posy + 1 | |
ydir = 0 | |
xdir = 1 | |
else: | |
#print("break") | |
loopon = 1 | |
break | |
elif xdir == 1 and ydir == 1: | |
if resized[posy, posx - 1] == 0: | |
#print("left") | |
posx = posx - 1 | |
posy = posy | |
xdir = 1 | |
elif resized[posy - 1, posx] == 0: | |
#print("up") | |
posx = posx | |
posy = posy - 1 | |
ydir = 1 | |
elif resized[posy - 1, posx - 1] == 0: | |
#print("upleft") | |
posx = posx - 1 | |
posy = posy - 1 | |
ydir = 1 | |
xdir = 1 | |
elif resized[posy, posx + 1] == 0: | |
#print("right") | |
posy = posy | |
posx = posx + 1 | |
xdir = 0 | |
elif resized[posy + 1, posx] == 0: | |
#print("down") | |
posx = posx | |
posy = posy + 1 | |
ydir = 0 | |
elif resized[posy + 1, posx - 1] == 0: | |
#print("downleft") | |
posx = posx - 1 | |
posy = posy + 1 | |
ydir = 0 | |
xdir = 1 | |
elif resized[posy - 1, posx + 1] == 0: | |
#print("upright") | |
posx = posx + 1 | |
posy = posy - 1 | |
ydir = 1 | |
xdir = 0 | |
elif resized[posy + 1, posx + 1] == 0: | |
#print("downright") | |
posy = posy + 1 | |
posx = posx + 1 | |
ydir = 0 | |
xdir = 0 | |
else: | |
#print("break") | |
loopon = 1 | |
break | |
resized[posy,posx] = 1 | |
usedpixels.append((posy, posx)) | |
usedpixels.append((posy, posx)) | |
for pos in usedpixels: | |
cv2.circle(resized, (pos[1],pos[0]), cs, (255,255,255),cv2.FILLED) | |
del usedpixels | |
gc.collect() | |
pyautogui.mouseUp(); | |
curcount = (resized == 0).sum() | |
progress = topcount - curcount | |
bar.update(progress) | |
#get image url and save it as lineart | |
url = input("Enter URL image: ") | |
bypass = input("Open paint?(y/n): ") | |
if url: | |
urllib.request.urlretrieve(url, "image.jpg") | |
if bypass == 'y': | |
os.system('mspaint.exe image.jpg') | |
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) | |
img2 = cv2.imread('image.jpg') | |
else: | |
img = cv2.imread('image2.png', cv2.IMREAD_GRAYSCALE) | |
img2 = cv2.imread('image2.png') | |
cs = input("Set Cursor Size in Pixels (4): ") | |
if cs == "": | |
cs = 4 | |
else: | |
cs = int(cs) | |
passit = False | |
pick_positions() | |
loopcount = input("Override Loops Per Pause (20000 default)") | |
if loopcount: | |
yyy = 0 | |
else: | |
loopcount = 20000 | |
draw_image(False) #set true to enable jackbox color thresholding | |
#print("\nAdd colors, switch to outline color, and then hit enter\n") | |
#keyboard.wait('enter') | |
#cs = cs2 | |
#draw_image() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment