Spaces:
Sleeping
Sleeping
File size: 17,409 Bytes
598008a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
import sys
from io import StringIO
import streamlit as st
import numpy as np
from PIL import Image, ImageDraw, ImageColor
from canvas import *
from streamlit_ace import st_ace
import extra_streamlit_components as stx
from sewar.full_ref import uqi
from lines import *
from triangle import *
st.set_page_config(page_title="How to play Shape Puzzle", page_icon=":notebook:")
with st.sidebar:
color = st.color_picker('color picker', '#00f900', key='l_c')
st.write(ImageColor.getrgb(color))
st.header("Chapter 1: Lines and Triangles")
st.write("##")
st.divider()
with st.expander("Tutorial No.1: Line segments"):
st.markdown("#### Let's start with playing with line-segments")
st.markdown(
"""
1. We will firstly draw a simple line-segment. The easiest way to do so is using our line function:
```python
line2P(start, point)
```
- In the code window below, define two points on the canvas by:
```python
a = (-100, 0) ## the x-axis is -100 and y-axis is 0
b = (100, 0) ## the x-axis is 100 and y-axis is 0
line2P(a, b) ## then call our line2P function to draw the line
```
You should see a horizontal line-segment in the canvas.
Feel free to change the color or the width of drawing by refering the "Functions" page from side bar.
2. Our 2nd Line function, LineDraw():
Sometimes, it might be easier to just start from a single point, but thinking about the direction and the length of drawing a
line segment. This is more intuitive for the real drawing scenario.
- In the code window below, define a point and the length and angle you want to draw :
```python
a = (-100, 0) ## the x-axis is -100 and y-axis is 0
angle = 45 ## 45 degree anti-clock wise
length = 200 ## length of the drawing
lineDraw(a, angle, length, width=50) ## then call our lineDraw function to draw the line
## We can also specify the width of drawing by passing parameter explicitly.
```
You should see a slant line-segment in the canvas.
3. Release the power of for-loop:
The most powerful part of drawing through code is the capability of producing iterative graphs.
The more detailed instruction about Python for-loops, please check [here](https://www.w3schools.com/python/python_for_loops.asp)
- In the code window below, define a startinig point and using for-loop and lineDraw:
```python
c = (-50,-100) ## The starting point to draw
lst = [c] ## Create a list for later reference
for i in range (100): ## Iterate 100 rounds
l = lineDraw(lst[-1], i*125, 300, (212, 16, 16), width=2) ## Try to figure out what are we doing here?
lst.append(l['end']) ## add the end-point of the line drawn to the list for the next iteration
```
4. Now, see if you can produce a shape stated in "target shape":
```python
s = (0,0) ## The starting point
n = 8 ##
lst = [s]
#### Start your for-loop here ####
#### End of your for-loop ####
```
Having fun!!
"""
)
st.divider()
st.markdown("###### Write your code here")
## Code input
code1 = st_ace(language="python", theme="tomorrow_night_bright", keybinding="vscode", font_size=14, tab_size=4, show_gutter=True, min_lines=10, key="ace",)
o1, o2 = st.columns(2)
if code1:
ImageDraw.Draw(img).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
redirected_output = sys.stdout = StringIO()
try:
exec(code1)
result = str(redirected_output.getvalue())
st.code(result)
except Exception as e:
st.code(str(e))
with o1:
st.markdown("##### Target Shape:"); target = Image.open('image/T1_t.jpg')
t2 = target.resize((c_length,c_height))
ImageDraw.Draw(img_t).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
img_t.paste(t2); st.image(img_t); st.session_state['imt'] = np.array(img_t)
with o2:
st.markdown("##### Output Shape"); st.image(img, caption=''); st.session_state['imo'] = np.array(img)
sim = round(uqi(st.session_state['imt'],st.session_state['imo']),4)
st.write(f"The similarity score between target and output: {sim}")
with st.expander("Tutorial No.2: Triangles and Transformations 1"):
st.markdown("Now, we will start to draw more cool shapes")
st.markdown(
"""
1. The simplest way to draw a triangle is to define three points on the canvas:
- In the code window below, define two points on the canvas by:
```python
a = (-100, 0) ## the x-axis is -100 and y-axis is 0
b = (100, 0) ## the x-axis is 100 and y-axis is 0
c = (0, 200) ## the x-axis is 0 and y-axis is 200
triangle_base(a,b,c, fill = (0, 249, 0), color=(0,0,0)) ## then call our basic triangle function to draw the shape
```
You should see a isosceles triangle in the canvas.
In the triangle_base() function, we have two parameters for coloring:
-- the "fill" is for the color filled in the triangle
-- the "color" is color of the edge of the triangle
2. Our 2nd Triangle function, triangle_LP():
Again, it might be easier to just start from a line, but thinking about another point to draw a
triangle. This is convient for some scenario when iteration applies.
- In the code window below, try the follow drawing:
```python
for i in range (10): # We create an iteration of 10
# Each iteration, draw a line with one different end point per iter
l = line2P((100,0+i*10),(-300,100), (0, 249, 0))
# then for each different line drawn, touch it to a fixed point (150,150) to form a triangle
triangle_LP(l, (150,150), (0, 249, 0))
```
You should see a repeated triangle shape in the canvas.
3. Transform of shapes 1: Rescale:
Shape transformations are very helpful functions in drawing shapes.
The first transformation we are trying is Rescale,
- In the code window below, define a startinig triangle from triangle_base() and then scale it:
```python
a = (-100, 0) ## the x-axis is -100 and y-axis is 0
b = (100, 0) ## the x-axis is 100 and y-axis is 0
c = (0, 200) ## the x-axis is 0 and y-axis is 200
### Our initial triangle, give it a name, t
t = triangle_base(a,b,c, fill = (0, 249, 0), color=(0, 249, 0))
### we rescale it with half size
### 1. We use the default color here, which was filled with canvas color and edge with black
### 2. We choose redraw=False, this means keep the original triangle t
##### 2.5 If we are passing redraw=True, the t will disappear.
t2 = rescale_c(t, alpha=0.5, redraw=False)
```
You might already see a chance of creating a for-loop for some great design?
The rescale function we used above is rescaling based on centre of triangle, we can also use another
rescale function rescale_p() to specify the point we want to base on for rescaling.
- In the code window below, following the code from above, paste the next snippet
```python
a = (-100, 0) ## the x-axis is -100 and y-axis is 0
b = (100, 0) ## the x-axis is 100 and y-axis is 0
c = (0, -200) ## the x-axis is 0 and y-axis is 200
### Our initial triangle, give it a name, t
t3 = triangle_base(a,b,c, fill = (201, 64, 26), color=(201, 64, 26))
### we rescale it with half size, but at different point
t4 = rescale_p(t3, 'p2', alpha=0.5, redraw=False)
```
4. Transform of shapes 2: Translation:
The second transformation we are introducing is translation,
- In the code window below, define a startinig triangle from triangle_base() and then Translate it
to different location:
```python
a = (-200, 0) ## the x-axis is -100 and y-axis is 0
b = (10, 0) ## the x-axis is 100 and y-axis is 0
c = (0, -100) ## the x-axis is 0 and y-axis is 200
### Our initial triangle, give it a name, t
t5 = triangle_base(a,b,c, fill = (201, 64, 26), color=(201, 64, 26))
## We use vector here to specify the direction and magnitute of translation.
## The translate_o() function is traslating triangles by a vector defined from the
## origin. i.e. the center of the canvas.
t6 = translate_o(t3, vector = (100,150), redraw=False)
```
Now we should try the effect of translate by a vector defined from a point of the triangle
- In the code window below, define a startinig triangle from triangle_base() and then Translate it
to different location, using translate_p() function:
```python
a = (-20, 0) ## the x-axis is -100 and y-axis is 0
b = (10, 0) ## the x-axis is 100 and y-axis is 0
c = (0, -100) ## the x-axis is 0 and y-axis is 200
### Our initial triangle, give it a name, t
t7 = triangle_base(a,b,c, fill = (201, 64, 26), color=(201, 64, 26))
translate_p(t7, vector = (-10,10), point = 'p2', redraw=False)
```
The code above specify "P2" as origin of translation rather than center of canvas
5. Using data for more complicated design:
Read the code below and check out the output from a more specific design
```python
b_line = line2P((-200,-160),(200,-160),color='black') # set the baseline
tpoint = (0,200) # set the top point of the triangle
# Create the first triangle
t1 = triangle_LP(b_line,tpoint,color='black',fill='black')
# Translate the triangle_LP
down_vector = (0,-50)
t2 = translate_o(t1, down_vector,fill=None, redraw=False)
# Redraw the edge of the second triangle
l1 = line2P(t2['p1'], t2['p2'], color='white', width=10)
l2 = line2P(t2['p1'], t2['p3'], color='white', width=10)
l3 = line2P(t2['p2'], t2['p3'], color='white', width=10)
## Find two intersections on the baseline
p1 = lines_intersection(l2, b_line)
p2 = lines_intersection(l3, b_line)
## Redraw the line-segment with information
l4 = line2P(p1, t2['p1'], color = 'black', width=10)
l5 = line2P(p2, t2['p2'], color = 'black', width=10)
l3 = line2P(t2['p1'], t2['p2'], color = 'black', width=10)
```
Feel free to play around the code above to try different design.
6. Try to design/create a shape like the target shape :)
"""
)
st.divider()
st.markdown("###### Write your code here")
## Code input
code2 = st_ace(language="python", theme="tomorrow_night_bright", keybinding="vscode", font_size=14, tab_size=4, show_gutter=True, min_lines=10, key="ace2",)
o1, o2 = st.columns(2)
if code2:
ImageDraw.Draw(img).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
redirected_output = sys.stdout = StringIO()
try:
exec(code2)
result = str(redirected_output.getvalue())
st.code(result)
except Exception as e:
st.code(str(e))
with o1:
st.markdown("##### Target Shape:"); target = Image.open('image/T2_t.jpg')
t2 = target.resize((c_length,c_height))
ImageDraw.Draw(img_t).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
img_t.paste(t2); st.image(img_t); st.session_state['imt'] = np.array(img_t)
with o2:
st.markdown("##### Output Shape"); st.image(img, caption=''); st.session_state['imo'] = np.array(img)
sim = round(uqi(st.session_state['imt'],st.session_state['imo']),4)
st.write(f"The similarity score between target and output: {sim}")
with st.expander("Tutorial No.3: Transformation 2, Rotation and Reflection"):
st.markdown("We will continues on more transformations that helps us to create shape designs")
st.markdown(
"""
1. Rotation by a point on the canvas:
- Copy and past the code below to the code window:
```python
P1=(100,100); P2=(200,50); P3=(-10,-50)
t = triangle_base(P1, P2, P3, 'red')
t1 = rotation(t,redraw=False, fill='blue') ## Rotation by the origin (0,0), default
# rotate 90 degree based on a point from the triangle
t2 = rotation(t, t['p1'], redraw = False, fill = 'yellow')
# rotate 120 degree based on a point on the canvas
t3 = rotation(t, (-50, 100), angle=120, redraw=False, fill='orange')
```
You should see differernt rotations with different color
Carefully read the code and comments, figuring out:
-- What is the parameter that control the point of rotation
-- what is the parameter that control the degree of rotation
2. Reflection by a line on the canvas:
- Copy and past the code below to the code window:
```python
P1=(100,100); P2=(200,50); P3=(-10,-50)
t = triangle_base(P1, P2, P3, 'red')
## Define different lines
l1 = line2P(t['p2'],t['p3'], 'green')
l2 = line2P((0,0),(0,200), 'yellow')
l3 = line2P((100,0),(200,0), 'orange')
## Reflect by different lines:
t3 = reflection(t, l1, redraw=False, fill='green')
t4 = reflection(t, l2, redraw=False, fill='yellow')
t5 = reflection(t, l3, redraw=False, fill='orange')
```
You should see differernt reflection with different color
Carefully read the code and comments, figuring out:
-- What is the parameter that control the line of reflection
3. Translations with for loops
Let's review the power of our favourate for-loops!
- Copy and past the code below to the code window:
```python
## You can define the colors you are using at the beginning
## To choose the color, using color picker to get the hex code or RGB values
B_color = 'white'
P_color = (11, 129, 11)
## Define an initial triangle
start = triangle_base((20,50),(20,80),(35,22.3),color=B_color)
start = rescale_c(start,3,color=B_color)
# try to reflect 1st time
a = reflection(start,line2P(start['p1'],start['p2'],P_color),
redraw=False,color=P_color)
## Looping around
for i in range(12):
a = reflection(a,line2P(a['p2'],a['p3']),redraw=False,color=P_color)
a = reflection(a,line2P(a['p1'],a['p3']),redraw=False,color=P_color)
## After reflection you might want to fine-tune to add on another rotation
reflection(a,line2P(a['p2'],a['p3'],P_color),redraw=False,color=P_color)
```
You might also try some different colors for the flower ---
4. Now, see if you can produce a shape stated in "target shape":
"""
)
st.divider()
st.markdown("###### Write your code here")
## Code input
code3 = st_ace(language="python", theme="tomorrow_night_bright", keybinding="vscode", font_size=14, tab_size=4, show_gutter=True, min_lines=10, key="ace3",)
o1, o2 = st.columns(2)
if code3:
ImageDraw.Draw(img).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
redirected_output = sys.stdout = StringIO()
try:
exec(code3)
result = str(redirected_output.getvalue())
st.code(result)
except Exception as e:
st.code(str(e))
with o1:
st.markdown("##### Target Shape:"); target = Image.open('image/T3_t.jpg')
t3 = target.resize((c_length,c_height))
ImageDraw.Draw(img_t).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
img_t.paste(t3); st.image(img_t); st.session_state['imt'] = np.array(img_t)
with o2:
st.markdown("##### Output Shape"); st.image(img, caption=''); st.session_state['imo'] = np.array(img)
sim = round(uqi(st.session_state['imt'],st.session_state['imo']),4)
st.write(f"The similarity score between target and output: {sim}") |