Skip to content

Instantly share code, notes, and snippets.

@tomatosoupcan
Last active March 4, 2021 04:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomatosoupcan/81a04fe30654b054561f7f4ba274bc90 to your computer and use it in GitHub Desktop.
Save tomatosoupcan/81a04fe30654b054561f7f4ba274bc90 to your computer and use it in GitHub Desktop.
Draw an image into Jackbox Games
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