r_place/python/clients.py

131 lines
3.4 KiB
Python
Raw Normal View History

2022-05-26 12:14:36 +00:00
#!/usr/bin/env python
import asyncio
from dataclasses import dataclass
2022-09-11 13:38:56 +00:00
import os
from socket import timeout
2022-06-07 12:50:40 +00:00
from PIL import Image
2022-05-26 12:14:36 +00:00
import json
2022-06-03 07:49:59 +00:00
from multiprocessing import Pool
import random
2022-05-26 12:14:36 +00:00
import time
2022-05-29 10:08:56 +00:00
from matplotlib import pyplot as plt
import numpy as np
2022-05-26 12:14:36 +00:00
import websockets
@dataclass
class pixel:
x: int
y: int
color: int
timestamp: int
userid: int
2022-09-11 13:38:56 +00:00
2022-06-07 12:50:40 +00:00
def hex_to_rgb(h):
2022-09-11 13:38:56 +00:00
return tuple(int(h[i : i + 2], 16) for i in (0, 2, 4))
2022-06-07 12:50:40 +00:00
hex_colors = [
2022-09-11 13:38:56 +00:00
"#FFFFFF",
"#E4E4E4",
"#888888",
"#222222",
"#FFA7D1",
"#E50000",
"#E59500",
"#A06A42",
"#E5D900",
"#94E044",
"#02BE01",
"#00D3DD",
"#0083C7",
"#0000EA",
"#CF6EE4",
"#820080",
]
2022-06-07 12:50:40 +00:00
rgb_colors = [hex_to_rgb(h[1:]) for h in hex_colors]
2022-09-11 13:38:56 +00:00
2022-06-07 12:50:40 +00:00
def eucleadian_distance(rgb1, rgb2):
if len(rgb1) != len(rgb2):
raise ValueError
2022-09-11 13:38:56 +00:00
sum_part = np.sum([(i-j) ** 2 for i, j in zip(rgb1, rgb2)])
2022-06-07 12:50:40 +00:00
# return np.sqrt(sum_part) # technically correct, but we only care about rank not exact distance and sqrt is expensive
return sum_part
2022-09-11 13:38:56 +00:00
2022-06-07 12:50:40 +00:00
def closest_match(rgb, color_map):
2022-09-11 13:38:56 +00:00
return min(
range(len(rgb_colors)), key=lambda i: eucleadian_distance(rgb, color_map[i])
)
2022-06-07 12:50:40 +00:00
2022-09-11 13:38:56 +00:00
async def sender(target, img):
start_x = random.randint(0, 900)
start_y = random.randint(0, 900)
max_w, max_h, _ = img.shape
async for websocket in websockets.connect(target + "/set"):
2022-06-19 18:42:01 +00:00
try:
2022-09-11 13:38:56 +00:00
for _ in range(int(max_h*max_w*1.3)):
rx = random.randint(0, max_w - 1)
ry = random.randint(0, max_h - 1)
if rx + start_x >= 1000 or ry + start_y >= 1000:
continue
message = pixel(
x=rx + start_x,
y=ry + start_y,
color=closest_match(img[rx][ry], rgb_colors),
timestamp=int(time.time()),
userid=1,
)
await websocket.send(json.dumps(message.__dict__))
succ = await websocket.recv()
if succ != "0":
print(message, "was not set")
return
except websockets.ConnectionClosed:
2022-06-19 18:42:01 +00:00
print("reconnecting")
2022-09-11 13:38:56 +00:00
async def client(target):
2022-05-31 14:15:09 +00:00
image = np.zeros(shape=[1000, 1000, 3], dtype=np.uint8)
2022-09-11 13:38:56 +00:00
async for websocket in websockets.connect(target + "/get"):
try:
2022-05-29 10:08:56 +00:00
x = pixel(**json.loads(await websocket.recv()))
2022-06-07 12:50:40 +00:00
image[x.x][x.y] = rgb_colors[x.color]
2022-05-31 14:15:09 +00:00
await websocket.send("1")
2022-09-11 13:38:56 +00:00
except websockets.ConnectionClosed:
continue
def rescale(max_dimension, img):
w, h = img.size
maxi = max([w, h])
scale = max_dimension / maxi
return img.resize((int(scale * w), int(scale * h)), Image.ANTIALIAS)
async def main(target):
images_folder_path = "./images"
while True:
image_paths = os.listdir(images_folder_path)
images = [
np.array(rescale(random.randint(100, 400), Image.open(f"{images_folder_path}/{image_path}")))
for image_path in image_paths
]
coros = [sender(target, images[i % len(images)]) for i in range(len(images))]
_ = await asyncio.gather(*coros)
def asyncMain(x, target):
asyncio.get_event_loop().run_until_complete(main(target))
2022-05-26 12:14:36 +00:00
if __name__ == "__main__":
2022-09-11 13:38:56 +00:00
# with Pool(12) as p:
2022-06-12 15:05:04 +00:00
# print(p.map(asyncMain, [() for _ in range(12)]))
2022-09-11 13:38:56 +00:00
asyncMain(0, target="ws://localhost:8080")