# Creating Desmos like plots

Desmos is a graphing calculator that people sometimes misuse for creating amazing graphics. I had created some graphs before :) Roger Federer, Pikachu, Deoxys

For creating these graphs, I had used simple tools mostly like ellipses, parabolas, circles, and straight lines. Believe me! It is a lot of fun. But, it takes a lot of time too.

So, I was thinking of automating it for a long time. I came across this inspirational video on YouTube that is a full fledged Desmos graph generator which uses Bezier curves to produce amazing Graphics. The video: How I animate stuff on Desmos Graphing Calculator. You can see the equations on the left and the plots as well

For this project, I am aiming for something simple though. I want to plot an image just using straight lines and produce those equations which can be imported into Desmos. Let’s get straight into the code.

# Libraries used

`import cv2 as cv`

import numpy as np

import matplotlib.pyplot as plt

import random

import warnings

warnings.filterwarnings("ignore")

# Image Processing

The whole project is based on simple image processing operations:

- canny edge detection of an input image
- detecting contours in the image and selecting which ones to keep based on a criterion (rejected the contours which had too few points(< 3) )
- for each contour, opencv returns a
**set of coordinates defining the contour.** - for each contour, I divided the contour into pairs of points. For example, if a contour is defined by the points [(1,1),(2,2),(3,3),(4,4)], we get 2 sets [(1,1),(2,2)] and [(3,3),(4,4)]
- For each set, say [(1,1),(2,2)], I fitted a line using y = mx + c. These equations are then pasted in an equation array.

#canny edge detection of input image

#detecting contours in the image and selecting which ones to keep #based on a criteria (rejected the contours which had too few #points(< 3) )img = cv.imread(r"C:\\Users\\Jojo\\Downloads\\fed.jpg")

img = cv.flip(img, 0)

imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

edged = cv.Canny(imgray, 40, 200)

ret, thresh = cv.threshold(edged, 50, 255, 0)

contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)r = cv.drawContours(img, contours, -1, (0,255,0), 3)

#cv.imshow('img',r)

#cv.waitKey(0)

res = []

s = 0

for i in contours:

if len(i)>3:

res.append(i)

s+=len(i)

r = cv.drawContours(img, res, -1, (0,255,0), 3)

Function for breaking a list into chunks:

`def chunks(lst, n):`

"""Yield successive n-sized chunks from lst."""

for i in range(0, len(lst), n):

yield lst[i:i + n]

Generating equations:

`strs `**=** []

pts **=** []

mb **=** []

**for** ele **in** res:

x **=** []

y **=** []

**for** k **in** ele:

x**.**append(k[0][0])

y**.**append(k[0][1])

**if** len(x)**%2** == 1:

x**.**pop()

**if** len(y)**%2** == 1:

y**.**pop()

g **=** list(chunks(x,2))

h **=** list(chunks(y,2))

pts**.**append(tuple(x))

pts**.**append(tuple(y))

pts**.**append(random**.**choice(['r','g','b']))

*#pts.append*

**for** i **in** range(len(g)):

**try**:

m, b **=** np**.**polyfit(g[i], h[i], 1)

st **=** 'y ='**+**str(m)**+**'*x+'**+**str(b)**+**'{'**+**str(min(h[i]))**+**'<y<'**+**str(max(h[i]))**+**'}'**+**'{'**+**str(min(g[i]))**+**'<x<'**+**str(max(g[i]))**+**'}'

strs**.**append(st)

mb**.**append([m, b, min(g[i]), max(g[i])])

**except**:

**continue**

Plotting the equations:

`plt`**.**figure(figsize**=**(10, 10))

plt**.**grid()

**for** i **in** range(len(mb)):

x **=** np**.**linspace(mb[i][2],mb[i][3],10)

y **=** mb[i][0]*****x**+**mb[i][1]

plt**.**plot(x, y, random**.**choice(['r','g','b']))

plt**.**grid()

plt**.**show()

# Results Gallery

Here are some results from my experiment.

There is room for improvements definitely as thresholding and edge detection parameters can be played with. Also, one can get better results with higher degree equations. If you want to collaborate, you can always create a pull request on Github.