DIY Drawing Tablet : Instructables
DIY Drawing Tablet : Instructables
by engineerkid1
Hello maker !
Few weeks ago I wanted to draw a digital art on my computer. I tried using my computer's mouse but that did not give
good results and the cost of commercial drawing tablets is so high that buying them for a single drawing is not really
worth it.
So, I decided to make my own drawing tablet. I made a simple pen that transmits IR rays when a push button is pressed.
And believe me that was all for the circuit part. The software part of this project was to track that pen and make it draw
on a canvas on my screen. And to do that I had to write a program that tracks the position of my pen and uses that
information to draw on a canvas.
I also ended up adding a couple of features to the software like the eraser, pen/background color selection, undo option,
bucket ll tool and most importantly a cursor option to just move around the canvas without drawing over it.
In this instructable, I will be guiding you on how you can make your own drawing tablet pen and use my software in your
computer. So, if you are interested then follow the next few steps and draw your rst digital master piece with your own
DIY Drawing Tablet.
Supplies:
1. Computer
2. Webcam
3. Veroboard
4. IR Led
5. Resistor (220 ohms)
6. Pushbutton
7. Single cell battery(if you want to make it wireless or else you can just use a USB cable to power the led)
8. Battery charging/protection circuit
9. Soldering iron to connect the components
10. Glue gun (optional)
https://youtu.be/WJH9s6tZq7o
If you don't have a webcam, you can still use this software with your smartphone as an IP camera.
But for that you will have to make some changes in the data le of the software. So, just go ahead and open the data.txt
le from the main folder. Once you open the le you will see two lines (Refer 2nd image). The rst line is basically the
index of your camera and that's what you will have to change. Also if you are using multiple webcams you can select a
particular camera by entering it's index here.
But before that open the IP webcam app on your phone and go to the video preferences. Note that you have to select
the video resolution as 640x480 (Refer 3rd image). Now start the server.
In the bottom you see a url which will help you access the video feed of the camera.
Now just type the url in the data text le in place of "0". And in the end of the url add a "/video" to get the feed.
Eg. http://192.168.0.103:8080/video
After this just save the data le and you are good to go.
The second line in the data le represents the color of the cursor. By default it is set to grey (127,127,127). You can change
it if you want.
By no means I claim that this software is a perfect replacement for drawing tablets. I mean, I named it Wack-om for a
reason. So, if you want to improve it or maybe add more features to it then I'm providing the source code below. Feel free
to modify it. Do note that my coding skills are worse than 13 year old's out there so, go through my code at your own risk.
import cv2
import numpy as np
from time import sleep
import webbrowser
cap = cv2.VideoCapture(camera_var)
fw, fh = 1080, 720
w, h = 640, 480
DIY Drawing Tablet ✏ : Page 9
w, h = 640, 480
doonce = 0
pointsList = []
prevX, prevY = 0, 0
old_bg = (0,0,0)
canvas = np.zeros((fh,fw,3),np.uint8)
canvas_copy = np.zeros((fh,fw,3),np.uint8)
canvas[:] = (0,0,0)
currX, currY = 0, 0
control_panel = np.zeros((100,600,3), np.uint8)
# Tuple to store undo redo x,y and t
x_y_t = []
global undo_redo_index
undo_redo_index = 0
bucket_selected = False
print("Print ESC Key To Close")
#Disable Tool
disable_tools = False
counter = 0
info_var = -1
# Status Variables
tool_ed, tool_sel, tool_color, bgr_color, tool_size, display_ed, undo_option = "No", "Brush", "(0,0,255)","(0,0,0)", "1", "Disable", "Not Available"
def empty(a):
pass
def create_Trackbars():
cv2.namedWindow("Control Panel")
cv2.resizeWindow("Control Panel",600,640)
cv2.createTrackbar("Main Feed","Control Panel",0,1,empty)
cv2.createTrackbar("Pen Red","Control Panel",255,255,empty)
cv2.createTrackbar("Pen Green","Control Panel",0,255,empty)
cv2.createTrackbar("Pen Blue","Control Panel",0,255,empty)
cv2.createTrackbar("Pen/E Size","Control Panel",1,50,empty)
cv2.createTrackbar("Bg Red","Control Panel",0,255,empty)
cv2.createTrackbar("Bg Green","Control Panel",0,255,empty)
cv2.createTrackbar("Bg Blue","Control Panel",0,255,empty)
cv2.createTrackbar("B / E / F","Control Panel",0,2,empty)
def GetStatus():
global tool_ed, tool_sel, tool_color, bgr_color, tool_size, display_ed, undo_option
print("--------------------------------------------------------")
print("Keyboard Shortcuts : Brush-b, Eraser-e, Bucket Fill-f")
print("Undo-z, Disable/Enable Tools-k, Close-ESC, Info-i")
print("--------------------------------------------------------")
print("Tools Disabled : "+tool_ed)
print("Tool Selected : "+tool_sel)
print("Tool Color : "+tool_color)
print("Background Color : "+bgr_color)
print("Tool Size : "+tool_size)
print("Main Feed Enabled/Disable : "+display_ed)
DIY Drawing Tablet ✏ : Page 10
print("Undo Option : "+undo_option)
def warpImage(frame):
frame = cv2.resize(frame, (fw,fh))
pts1 = np.float32([pointsList[3], pointsList[2], pointsList[1], pointsList[0]])
pts2 = np.float32([[0,0], [w,0], [0,h], [w,h]])
matrix = cv2.getPerspectiveTransform(pts1, pts2)
output = cv2.warpPerspective(frame, matrix, (w,h))
return output
if doonce == 0:
global imgr
ret, img = cap.read()
imgr = cv2.resize(img, (fw,fh))
cv2.putText(imgr, "Point 1",(5,30),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),3)
cv2.putText(imgr, "Point 2",(954,30),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),3)
cv2.putText(imgr, "Point 3",(5,705),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),3)
cv2.putText(imgr, "Point 4",(954,705),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),3)
cv2.putText(imgr, "Please Consider Subscribing - Engineer Kid",(180,330),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2)
cv2.putText(imgr, "CLICK HERE !",(420,377),cv2.FONT_HERSHEY_SIMPLEX,1,(0,0,255),3)
cv2.rectangle(imgr, (414,345), (637,390), (0,0,255), 3)
cv2.imshow("Frame",imgr)
cv2.setMouseCallback('Frame', getPoints)
while True:
if doonce == 1:
cv2.destroyWindow("Frame")
disp_mainfeed = cv2.getTrackbarPos("Main Feed","Control Panel")
red_value = cv2.getTrackbarPos("Pen Red","Control Panel")
green_value = cv2.getTrackbarPos("Pen Green","Control Panel")
blue_value = cv2.getTrackbarPos("Pen Blue","Control Panel")
pen_color = (blue_value,green_value,red_value)
pen_thickness = cv2.getTrackbarPos("Pen/E Size", "Control Panel")
bg_red = cv2.getTrackbarPos("Bg Red", "Control Panel")
bg_green = cv2.getTrackbarPos("Bg Green", "Control Panel")
bg_blue = cv2.getTrackbarPos("Bg Blue", "Control Panel")
tool_select = cv2.getTrackbarPos("B / E / F", "Control Panel")
if old_bg != (bg_blue,bg_green,bg_red):
canvas[:] = (bg_blue,bg_green,bg_red)
old_bg = (bg_blue,bg_green,bg_red)
if pen_thickness < 1:
pen_thickness = 1
ret, frame = cap.read()
output = warpImage(frame)
output = cv2.resize(output, (fw,fh))
input_image = output.copy()
low_b = np.uint8([255,255,255])
high_b = np.uint8([255,255,255])
mask = cv2.inRange(output, high_b, low_b)
contours, heirarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
tool_color = str(pen_color)
bgr_color = str((bg_blue,bg_green,bg_red))
tool_size = str(pen_thickness)
if len(contours) > 0 :
c = max(contours, key=cv2.contourArea)
M = cv2.moments(c)
if M["m00"] !=0 :
currX = int(M['m10']/M['m00'])
currY = int(M['m01']/M['m00'])
if prevX==0 and prevY==0:
prevX = currX
prevY = currY
if tool_select == 0 and disable_tools == 0:
undo_option = "Available"
cv2.line(canvas, (prevX,prevY), (currX,currY), pen_color, pen_thickness)
all_values = (currX,currY),(prevX,prevY),pen_thickness,(bg_blue,bg_green,bg_red)
x_y_t.append(all_values)
undo_redo_index = len(x_y_t)-1
if len(x_y_t) > 250:
x_y_t.pop(0)
undo_redo_index = len(x_y_t)-1
DIY Drawing Tablet ✏ : Page 11
undo_redo_index = len(x_y_t)-1
if tool_select == 1 and disable_tools == 0:
undo_option = "Not Available"
cv2.line(canvas, (prevX,prevY), (currX,currY), (bg_blue,bg_green,bg_red), pen_thickness)
if tool_select == 2 and disable_tools == 0:
undo_option = "Not Available"
mask_fill = np.zeros([fh+2, fw+2], np.uint8)
cv2.floodFill(canvas, mask_fill, (currX,currY), pen_color, (100,100,100), (50,50,50), cv2.FLOODFILL_FIXED_RANGE)
if disable_tools == -1:
undo_option = "Not Available"
if counter == 0:
canvas_copy = canvas.copy()
canvas_copy2 = canvas.copy()
counter = 1
if counter == 1:
canvas_copy3 = canvas_copy2
cv2.circle(canvas_copy3, (currX,currY), 3, cursor_color, cv2.FILLED)
canvas = canvas_copy3
cv2.imshow("WACKOM - MADE By Engineer Kid",canvas)
sleep(0.01)
canvas = canvas_copy2
if disable_tools == 0:
canvas = canvas_copy
counter = 0
prevX = currX
prevY = currY
#print("Detected")
else:
prevX = 0
prevY = 0
canvas = canvas_copy
counter = 0
#print("Not Detected")
if disp_mainfeed == 1:
display_ed = "Enabled"
cv2.imshow("Main Feed",input_image)
else:
display_ed = "Disabled"
cv2.destroyWindow("Main Feed")
if info_var == 0:
GetStatus()
cv2.imshow("WACKOM - MADE By Engineer Kid",canvas)
if disable_tools == 0:
control_panel[0:39] = pen_color
control_panel[59:100] = (bg_blue,bg_green,bg_red)
elif disable_tools == -1:
control_panel[0:39] = cursor_color
control_panel[59:100] = cursor_color
cv2.putText(control_panel, "Brush Color -",(5,30),cv2.FONT_HERSHEY_SIMPLEX,1,(bg_blue,bg_green,bg_red),2)
cv2.putText(control_panel, "BGR Color -",(5,90),cv2.FONT_HERSHEY_SIMPLEX,1,pen_color,2)
cv2.imshow("Control Panel", control_panel)
If you liked this little project then you can support me by subscribing my YouTube channel. Also, if you make this project
or improve it then do let me know (if you wish). I would love to hear what features you have added. So, yeah this is it.
Have a great time and stay creative :)