132 lines
3.5 KiB
Python
132 lines
3.5 KiB
Python
|
from pyaxidraw import axidraw
|
||
|
import time
|
||
|
import subprocess
|
||
|
import io
|
||
|
from PIL import Image
|
||
|
import datetime
|
||
|
import tqdm
|
||
|
|
||
|
|
||
|
import colorsys
|
||
|
|
||
|
|
||
|
# TODO: argparse: skip_draw, skip_scan, loop [n times]
|
||
|
|
||
|
class Level(object):
|
||
|
|
||
|
def __init__(self, minv, maxv, gamma):
|
||
|
self.minv= minv/255.0
|
||
|
self.maxv= maxv/255.0
|
||
|
self._interval= self.maxv - self.minv
|
||
|
self._invgamma= 1.0/gamma
|
||
|
|
||
|
def new_level(self, value):
|
||
|
if value <= self.minv: return 0.0
|
||
|
if value >= self.maxv: return 1.0
|
||
|
return ((value - self.minv)/self._interval)**self._invgamma
|
||
|
|
||
|
def convert_and_level(self, band_values):
|
||
|
h, s, v= colorsys.rgb_to_hsv(*(i/255.0 for i in band_values))
|
||
|
new_v= self.new_level(v)
|
||
|
return tuple(int(255*i)
|
||
|
for i
|
||
|
in colorsys.hsv_to_rgb(h, s, new_v))
|
||
|
|
||
|
def level_image(image, minv=0, maxv=255, gamma=1.0):
|
||
|
"""Level the brightness of image (a PIL.Image instance)
|
||
|
All values ≤ minv will become 0
|
||
|
All values ≥ maxv will become 255
|
||
|
gamma controls the curve for all values between minv and maxv"""
|
||
|
|
||
|
if image.mode != "RGB":
|
||
|
raise ValueError("this works with RGB images only")
|
||
|
|
||
|
new_image= image.copy()
|
||
|
|
||
|
leveller= Level(minv, maxv, gamma)
|
||
|
levelled_data= [
|
||
|
leveller.convert_and_level(data)
|
||
|
for data in image.getdata()]
|
||
|
new_image.putdata(levelled_data)
|
||
|
return new_image
|
||
|
|
||
|
now = datetime.datetime.now().isoformat()
|
||
|
|
||
|
print(f"test plotter/scanner/pen at {now}")
|
||
|
|
||
|
absPlotWidth = 26.5/2.54
|
||
|
topLeft = absPlotWidth / (245/ 10 / 2.54)
|
||
|
parkX = (1/2.54)/absPlotWidth + topLeft
|
||
|
parkPos = [26.5/2.54,2,0]
|
||
|
print(parkPos)
|
||
|
|
||
|
ad = axidraw.AxiDraw()
|
||
|
|
||
|
ad.interactive()
|
||
|
ad.connect()
|
||
|
ad.pen_raise()
|
||
|
ad.disconnect()
|
||
|
|
||
|
ad = axidraw.AxiDraw()
|
||
|
ad.plot_setup('test_drawing.svg') # Load file & configure plot context
|
||
|
# Plotting options can be set, here after plot_setup().
|
||
|
ad.plot_run()
|
||
|
ad.disconnect()
|
||
|
|
||
|
|
||
|
|
||
|
ad = axidraw.AxiDraw()
|
||
|
# park
|
||
|
ad.interactive()
|
||
|
ad.connect()
|
||
|
ad.pen_raise()
|
||
|
ad.moveto(parkPos[0], parkPos[1])
|
||
|
|
||
|
try:
|
||
|
sleeptime = 2
|
||
|
print(f"plotted, now wait for the ink to dry {sleeptime}s")
|
||
|
|
||
|
for i in tqdm.tqdm(range(sleeptime)):
|
||
|
time.sleep(1)
|
||
|
|
||
|
|
||
|
cmd = [
|
||
|
'sudo', 'scanimage', '-d', 'epkowa', '--format', 'tiff',
|
||
|
'--resolution=100', # lower res, faster (more powerful) scan & wipe
|
||
|
'-l','25' #y axis, margin from top of the scanner, hence increasing this, moves the scanned image upwards
|
||
|
,'-t','22', # x axis, margin from left side scanner (seen from the outside)
|
||
|
'-x',str(181),
|
||
|
'-y',str(245)
|
||
|
]
|
||
|
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||
|
# opens connection to scanner, but only starts scanning when output becomes ready:
|
||
|
o, e = proc.communicate(80)
|
||
|
|
||
|
print('scanned')
|
||
|
|
||
|
f = io.BytesIO(o)
|
||
|
img = Image.open(f)
|
||
|
img = img.transpose(Image.ROTATE_90).transpose(Image.FLIP_TOP_BOTTOM)
|
||
|
img.save(f'test-{now}.png')
|
||
|
print(f'\tsaved to test-{now}.png')
|
||
|
|
||
|
print('effects:')
|
||
|
leveldImg = level_image(img, 0, 125, 0.95)
|
||
|
leveldImg.save(f'test-{now}-leveled.png')
|
||
|
print(f'\tsaved to test-{now}-leveled.png')
|
||
|
except Exception as e:
|
||
|
print(e)
|
||
|
finally:
|
||
|
time.sleep(5) # scanner says its done before it slides back
|
||
|
print('reset pen')
|
||
|
ad.moveto(0,0)
|
||
|
ad.disconnect()
|
||
|
|
||
|
print('disable motors')
|
||
|
# disable motors
|
||
|
ad = axidraw.AxiDraw()
|
||
|
ad.plot_setup()
|
||
|
ad.options.mode = "manual"
|
||
|
ad.options.manual_cmd = "disable_xy"
|
||
|
ad.plot_run()
|