Featured

It is here: Under the Magical Sky

It is here…

After a year of hard work and dedication, we are pleased to announce the launch of our first book and brand new website! Under the magical is finally here!

We are very proud of the result, excited about the future and so grateful for the opportunity to make a difference.

We are deeply passionate about creativity and arts, but can’t ignore the fact that millions of children face the least stable living and learning circumstances every day. That’s why we have decided that every time you purchase at Under the Magical Sky, we will donate to those in need.

Now, we invite you all to visit our site: https://underthemagicalsky.com/

Under The Magical Sky. By Valeria Bressan and Tauno Erik

Motion detection on the webcam

It is surprisingly easy to make a small Python script that takes a webcam or any other video and detects when something is moving there. It uses the OpenCV library.

1. Difference between frames

Compares two frames and displays only what are change. The rest is black.

import cv2

# Select camera. Usualy 0, or 1 and so on
cam = cv2.VideoCapture(0)

try:
	while cam.isOpened():
		ret, frame1 = cam.read()
		ret, frame2 = cam.read()
		diff = cv2.absdiff(frame1, frame2)
    
		# To exit press 'q'    
		if cv2.waitKey(10) == ord('q'):
			break
    	
		# Display
		cv2.imshow('Erinevus', diff)
except:
	print("Error.")

2. Binary image

Turn it into binary: only black and white. To make it easy to find contours.

import cv2

# Select camera. Usualy 0, or 1 and so on
cam = cv2.VideoCapture(0)

try:
	while cam.isOpened():
		ret, frame1 = cam.read()
		ret, frame2 = cam.read()
		# Compare frames
		diff = cv2.absdiff(frame1, frame2)
		# Convert diff to grayscale image
		gray = cv2.cvtColor(diff, cv2.COLOR_RGB2GRAY)
		# Blur gray image
		blur = cv2.GaussianBlur(gray, (5, 5), 0)
		# Converts to Binary images. Only black and white colour.
		_, thresh = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY)
		# Expand moving image part
		dilated = cv2.dilate(thresh, None, iterations=3)
    
		# To exit press 'q'    
		if cv2.waitKey(10) == ord('q'):
			break
    	
		# Display
		cv2.imshow('Erinevus', dilated)
except:
	print("Error.")

3. Contours

Now displays founded contours over the original image.

import cv2

# Select camera. Usualy 0, or 1 and so on
cam = cv2.VideoCapture(0)

try:
	while cam.isOpened():
		ret, frame1 = cam.read()
		ret, frame2 = cam.read()
		# Compare frames
		diff = cv2.absdiff(frame1, frame2)
		# Convert diff to grayscale image
		gray = cv2.cvtColor(diff, cv2.COLOR_RGB2GRAY)
		# Blur gray image
		blur = cv2.GaussianBlur(gray, (5, 5), 0)
		# Converts to Binary images. Only black and white colour.
		_, thresh = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY)
		# Expand moving image part
		dilated = cv2.dilate(thresh, None, iterations=3)
		# Find moving part contures
		contours, _ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
		# Draw contours
		cv2.drawContours(frame1, contours, -1, (0, 255, 0), 2) #
    
		# To exit press 'q'    
		if cv2.waitKey(10) == ord('q'):
			break
    	
		# Display
		cv2.imshow('Erinevus', frame1)
except:
	print("Error.")

Rectangle

When we know where the contours are. Where are the coordinates of the beginning on the x and y axes. We can draw rectangles around these regions.

import cv2

# Select camera. Usualy 0, or 1 and so on
cam = cv2.VideoCapture(0)

try:
	while cam.isOpened():
		ret, frame1 = cam.read()
		ret, frame2 = cam.read()
		# Compare frames
		diff = cv2.absdiff(frame1, frame2)
		# Convert diff to grayscale image
		gray = cv2.cvtColor(diff, cv2.COLOR_RGB2GRAY)
		# Blur gray image
		blur = cv2.GaussianBlur(gray, (5, 5), 0)
		# Converts to Binary images. Only black and white colour.
		_, thresh = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY)
		# Expand moving image part
		dilated = cv2.dilate(thresh, None, iterations=3)
		# Find moving part contures
		contours, _ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

		for c in contours:
			# Select movement size area.
			# If contour is smaller it will be ignored.
			if cv2.contourArea(c) < 2000:
				continue
			# Contour position and size
			x, y, w, h = cv2.boundingRect(c)
			# Draw rectangle
			cv2.rectangle(frame1, (x, y), (x+w, y+h), (0, 255, 0), 2)
			# To something
    
		# To exit press 'q'    
		if cv2.waitKey(10) == ord('q'):
			break
    	
		# Display
		cv2.imshow('Liikumine', frame1)
except:
	print("Error.")

Demo video

Custom Wooden Mechanical Keyboard

I had one old and cheap rubber dome keyboard with missing keys. So I take it apart and found this controller PCB board. The board pads were coated with graphite. I removed it and soldered wires on it. And put it on a breadboard. Then I mapped all rows and column combinations to find what scancode they output. For this, I have the python script to display which key is pressed.


Then I designed PCB for one switch. It is with breadboard friendly layout and uses through-hole components. And made a plywood mounting plate, stained it black and lacquered. I connected the buttons through the mounting plate to the circuit boards.


Then I figured out which buttons I wanted and soldered right C and R wires in the right places.


I also made a plywood case.


The next part was keycaps. I could use plastic ones. But I wanted them to be symmetrical and with symbols on them. So again I made them from plywood. The top layer is solid oak. Other is birch tree plywood. Laser cutting them and glued together. One part is 3D printed. Cross shape part that connects keycaps to switches. The hardest part was sanding the keycaps to the right shape. I did it by hand, but it should be mechanized process. And also my keycaps are larger than normal keycaps on the keyboard.


All wooden parts are finished with Liberon Black Bison Antikvax.

Links:

How i made my digital radio

This is my simple one-button radio. One button to turn it on and change the volume. There are actually two buttons more: first to select a new channel and second one to save it to memory.

It was a project that taught me how to draw PCBs, what are Gerber files and so on. I designed 4 different layouts, orders two. The first one had some noise problems. So I added some filters and ordered the second one.

It works and I am happy with it mostly. I do not have any education in electronics, so forgive me if it does not meet professional standards.

It is now my second stop motion animation. It took about a week to do. It could be better if I put more time into it.

Schematics

It uses Arduino Nano as the main control unit.

Code

Old (Ancient Egyptian) solid wood items

Ancient Egyptian wooden furniture. I love this kind of old wood items: aged and natural. I especially chose the ones that would not be overpainted and decorated.

Link: https://collections.louvre.fr/en/ark:/53355/cl010017034

Link: https://collections.louvre.fr/en/ark:/53355/cl010018558

Link: https://collections.louvre.fr/en/ark:/53355/cl010024942

Link: https://collections.louvre.fr/en/ark:/53355/cl010007843

Link: https://collections.louvre.fr/en/ark:/53355/cl010006806

Link: https://collections.louvre.fr/en/ark:/53355/cl010010764

Link: https://collections.louvre.fr/en/ark:/53355/cl010010823

Link: https://collections.louvre.fr/en/ark:/53355/cl010008109

Link: https://collections.louvre.fr/en/ark:/53355/cl010036860

Link: https://collections.louvre.fr/en/ark:/53355/cl010008763

Link: https://collections.louvre.fr/en/ark:/53355/cl010008450

Link: https://collections.louvre.fr/en/ark:/53355/cl010008519

Link: https://collections.louvre.fr/en/ark:/53355/cl010007198

Link: https://collections.louvre.fr/en/ark:/53355/cl010037301

Link: https://collections.louvre.fr/en/ark:/53355/cl010006589

Link: https://collections.louvre.fr/en/ark:/53355/cl010007030

Link: https://collections.louvre.fr/en/ark:/53355/cl010007473

Link: https://collections.louvre.fr/en/ark:/53355/cl010029163

Link: https://collections.louvre.fr/en/ark:/53355/cl010034013

Link: https://collections.louvre.fr/en/ark:/53355/cl010011663

Link: https://collections.louvre.fr/en/ark:/53355/cl010011263

Link: https://collections.louvre.fr/en/ark:/53355/cl010006782

Kõige tavalisem värv pildil

On juhtumid, kus meid ei huvita üksikute pikslite värv. Vaid tahame üldist summeeritud keskmist. Näiteks põllumajanduses saab värvipõhjal hinnata puu või köögivilja küpsusastet.

Alustuseks laeme vajalikud teegid:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
import PIL
from skimage import io
%matplotlib inline

#Kõik pildid on siin kataloogis
kataloog = 'https://raw.githubusercontent.com/taunoe/jupyter-notebooks/main/Pildi-anal%C3%BC%C3%BCs/images/'

Teeme funktsiooni, mis aitab näidata kahte pilti kõrvuti.

def show_img_compar(pilt_1, pilt_2 ):
    f, ax = plt.subplots(1, 2, figsize=(10,10))
    ax[0].imshow(pilt_1)
    ax[1].imshow(pilt_2)
    ax[0].axis('on')  # Kuva koordinaatteljestik
    ax[1].axis('off') # Peida koordinaatteljestik
    f.tight_layout()
    plt.show()

Valime pildid:

#pilt_1 = cv.imread(kataloog + 'tamm.jpg') # annab errori
pilt_1 = io.imread(kataloog + 'tamm.jpg')
#pilt_1 = cv.cvtColor(pilt_1, cv.COLOR_BGR2RGB) # reastab BGR kihid ümber RGBks
pilt_2 = io.imread(kataloog + 'sinie.jpg')
#pilt_2 = cv.cvtColor(pilt_2, cv.COLOR_BGR2RGB)

Teeme pilte väiksemaks:

dim = (500, 300)
# Pildid väiksemaks
pilt_1 = cv.resize(pilt_1, dim, interpolation = cv.INTER_AREA)
pilt_2 = cv.resize(pilt_2, dim, interpolation = cv.INTER_AREA)

Proovime, kas piltide kuvamine töötab:

Meetod 1 – keskmine pikslite väärtus

Kõige lihtsam meetod on leida pikslite keskmised väärtused. Kasutades teegist numpy average funktsiooni leidmaks keskmise piksli väärtus.

Selline meetod võib anda ebatäpseid tulemusi. Eriti, kui pildi pinnal on suuri kontrasti (heledate ja tumedate alade) erinevusi. Tamme tekstuuri puhul on aga tulemus üsna usutav.

img_temp = pilt_1.copy()
img_temp[:,:,0], img_temp[:,:,1], img_temp[:,:,2] = np.average(pilt_1, axis=(0,1))
show_img_compar(pilt_1, img_temp)
img_temp = pilt_2.copy()
img_temp[:,:,0], img_temp[:,:,1], img_temp[:,:,2] = np.average(pilt_2, axis=(0,1))
show_img_compar(pilt_2, img_temp)
pilt_3 = io.imread(kataloog + 'muster.jpg') # impordime pildi
pilt_3 = cv.resize(pilt_3, dim, interpolation = cv.INTER_AREA) # muudame suurust
img_temp = pilt_3.copy() # teeme koopia
img_temp[:,:,0], img_temp[:,:,1], img_temp[:,:,2] = np.average(pilt_3, axis=(0,1)) # arvutame keskmise
show_img_compar(pilt_3, img_temp) # kuvame tulemused

Meetod 2 – levinuima värviga pikslid

Teine meetod on natuke täpsem, kui esimene. Loeme iga piksli väärtuse esinemise sagedust.

img_temp = pilt_3.copy()
unique, counts = np.unique(img_temp.reshape(-1, 3), axis=0, return_counts=True)
img_temp[:,:,0], img_temp[:,:,1], img_temp[:,:,2] = unique[np.argmax(counts)]
show_img_compar(pilt_3, img_temp)
Selle pildi puhul on tausta hall kõige levinum värv ja tulemus ei ole see mida ootasime.
img_temp_2 = pilt_2.copy()
unique, counts = np.unique(img_temp_2.reshape(-1, 3), axis=0, return_counts=True)
img_temp_2[:,:,0], img_temp_2[:,:,1], img_temp_2[:,:,2] = unique[np.argmax(counts)]
show_img_compar(pilt_2, img_temp_2)

Meetod 3 – levinumad värvi grupid pildil

K-keskmiste klasteradmine – jagame pikslid värvi läheduse järgi klastritesse. Ja vaatame, mis on keskmine värv klastrites.

from sklearn.cluster import KMeans

clt = KMeans(n_clusters=5) # Klastrite arv

Funktsioon värvipaletti koostamiseks.

def palette(clusters):
    width=300
    height=50
    palette = np.zeros((height, width, 3), np.uint8)
    steps = width/clusters.cluster_centers_.shape[0]
    for idx, centers in enumerate(clusters.cluster_centers_): 
        palette[:, int(idx*steps):(int((idx+1)*steps)), :] = centers
    return palette
clt_1 = clt.fit(pilt_3.reshape(-1, 3))
show_img_compar(pilt_3, palette(clt_1))
clt_2 = clt.fit(pilt_2.reshape(-1, 3))
show_img_compar(pilt_2, palette(clt_2))

Meetod 4 – levinumad värvi grupid proportsionaalselt

Sisuliselt sama, mis eelmine aga leitud värve kuvab proportsionaalselt selle levikuga. Kui mingit värvi on rohkem, siis selle ristkülik on ka suurem ja vastupidi.

Abifunktsioon värvipaletti kuvamiseks:

from collections import Counter

def palette_perc(k_cluster):
    width = 300
    height = 50
    palette = np.zeros((height, width, 3), np.uint8)
    
    n_pixels = len(k_cluster.labels_)
    counter = Counter(k_cluster.labels_) # count how many pixels per cluster
    perc = {}
    for i in counter:
        perc[i] = np.round(counter[i]/n_pixels, 2)
    perc = dict(sorted(perc.items()))
    
    #for logging purposes
    #print(perc)
    #print(k_cluster.cluster_centers_)
    
    step = 0
    
    for idx, centers in enumerate(k_cluster.cluster_centers_): 
        palette[:, step:int(step + perc[idx]*width+1), :] = centers
        step += int(perc[idx]*width+1)
        
    return palette
clt_1 = clt.fit(pilt_3.reshape(-1, 3))
show_img_compar(pilt_3, palette_perc(clt_1))
clt_2 = clt.fit(pilt_2.reshape(-1, 3))
show_img_compar(pilt_2, palette_perc(clt_2))
pilt_4 = io.imread(kataloog + 'klaster1.jpg') # Impordime pildi
pilt_4 = cv.resize(pilt_4, dim, interpolation = cv.INTER_AREA) # Pilt väiksemaks
clt_4 = clt.fit(pilt_4.reshape(-1, 3))
show_img_compar(pilt_4, palette_perc(clt_4))
pilt_5 = io.imread(kataloog + 'wermo1.png') # Impordime pildi
#pilt_5 = cv.resize(pilt_5, dim, interpolation = cv.INTER_AREA) # Pilt väiksemaks
clt_5 = clt.fit(pilt_5.reshape(-1, 3))
show_img_compar(pilt_5, palette_perc(clt_5))
pilt_7 = io.imread(kataloog + 'kevad.jpg') # Impordime pildi
#pilt_7 = cv.resize(pilt_6, (500, 500) , interpolation = cv.INTER_AREA) # Pilt väiksemaks
clt_7 = clt.fit(pilt_7.reshape(-1, 3))
show_img_compar(pilt_7, palette_perc(clt_7))

Lingid:

Sissejuhatus pildiliste andmete töötlusse ja analüüsi 2.

Maskid

Maskid on selleks, et mingi osa pildist kinni katta.

pilt = imageio.imread(kataloog + 'image.jpg')

# seperate the row and column values  
total_row , total_col , layers = pilt.shape  
''' Create vector.
Ogrid is a compact method of creating a multidimensional
ndarray operations in single lines.     
for ex:     
>>> ogrid[0:5,0:5]     
output: [array([[0],
                [1],
                [2],
                [3],
                [4]]),
         array([[0, 1, 2, 3, 4]])]  
''' 
x , y = np.ogrid[:total_row , :total_col]  
# get the center values of the image 
cen_x , cen_y = total_row/2 , total_col/2  
'''    
 Measure distance value from center to each border pixel.
 To make it easy, we can think it's like, we draw a line from center-
 to each edge pixel value --> s**2 = (Y-y)**2 + (X-x)**2  
''' 
distance_from_the_center = np.sqrt((x-cen_x)**2 + (y-cen_y)**2)

radius = (total_row/2)  # Arvutame raadiuse
# Using logical operator '>'  
# logical operator to do this task which will return as a value
# of True for all the index according to the given condition. 
ymmargune_pilt = distance_from_the_center > radius  
 
pilt[ymmargune_pilt] = 0 # maski värv 0-255
#plt.figure(figsize = (5,5)) 
plt.imshow(pilt)  
plt.show()

Filtreerimine

Näiteks filtreerime välja pikslid mille väärtus on suurem, kui 200. Ja värvime need mustaks (anname väärtuse 0).

pilt = imageio.imread(kataloog +'image.jpg') 
valitud_pikslid = pilt > 200 #  

pilt[valitud_pikslid] = 0 # uue väärtuse andmine
plt.imshow(pilt) 
plt.show()

Maskide ja filtreerimise näide

nimi = 'katsekeha1.jpg'
pilt = imageio.imread(kataloog + nimi)

plt.title('Originaal pilt') 
plt.imshow(pilt)
plt.show()

Kuva ainult punased pikslid mille väärtus on väiksem, kui 235:

pilt = imageio.imread(kataloog + nimi)
red_mask = pilt[:, :, 0] > 235
pilt[red_mask] = 0 # Maski toon: 0 must, 255 valge
plt.imshow(pilt)

Ainult rohelised pikslid mille väärtus väiksem, kui 220:

pilt = imageio.imread(kataloog + nimi)
green_mask = pilt[:, :, 1] > 225
pilt[green_mask] = 0 # Maski toon: 0 must, 255 valge
plt.imshow(pilt)

Ainult sinised pikslid, mille väärtus väiksem, kui 200:

pilt = imageio.imread(kataloog + nimi)
blue_mask = pilt[:, :, 2] > 210
pilt[blue_mask] = 0
plt.imshow(pilt)

Pilt, kus on kõik kolm maski ühendatud:

pilt = imageio.imread(kataloog + nimi)
final_mask = np.logical_and(red_mask, green_mask, blue_mask)
pilt[final_mask] = 0 # Maski toon: 0 must, 255 valge
plt.imshow(pilt)

Histogram

Histogrammi saame kasutada, et näidada mingi värvitooni esinemissagedust pildil.

  • Histogram näitab värvitooni intensiivsuse jaotumist pildil.
  • Histogram näitab, kui palju mingi intensiivsusega piksleid on.
import cv2
import numpy as np
from matplotlib import pyplot as plt

kataloog = 'https://raw.githubusercontent.com/taunoe/jupyter-notebooks/main/Pildi-anal%C3%BC%C3%BCs/images/'
hall_img = imageio.imread(kataloog + 'image_hall.jpg')

hist,bins = np.histogram(hall_img, 256,[0,256])
plt.hist(hall_img.ravel(),256,[0,256])
plt.title('Hall toonides pildi histogramm')
plt.ylabel('Pikslite hulk')
plt.xlabel('Värvi väärtus')
plt.show()

Värvilise pildi RGB toonide histogram:

img = imageio.imread(kataloog + 'image.jpg')
plt.imshow(img)
plt.show()

color = ('b','g','r')
for channel,col in enumerate(color):
    histr = cv2.calcHist([img],[channel],None,[256],[0,256])
    plt.plot(histr,color = col)
    plt.xlim([0,256])
plt.title('RGB histogramm')
plt.ylabel('Pikslite hulk')
plt.xlabel('Värvi väärtus')
plt.show()

Lingid

Sissejuhatus pildiliste andmete töötlusse ja analüüsi 1.

Antud materjali koostamise eesmärgiks on leida viise, kuidas hinnata objektiivselt pilte ja neil olevat informatsiooni. Et tulemused oleksid mõõdetavad, võrreldavad ja neid saaks teostada automaatselt.

Töövahendite tutvustus

Jupyter märkmik

Jupyter notebook on veebipõhine interaktiivne keskkond, kus saab vaheldumisi kirjutada teksti ja käivitatavaid koodi (python) lahtreid. Et midagi arvutada, töödelda andmeid, kuvada graafikuid jne. Selle kasutamine on väga levinud andmeteadustes, masinõppes ja hariduses.

Colab on Google poolt majutatav Jupyter notebook.

Python

Python on üldotstarbeline programmeerimiskeel. Pythonit peetakse küllaltki lihtsaks keeleks, milles tavaliselt alustatakse programmeerimise õppimist. Kasutamise eeliseks on ka see, et on juba loodud väga palju valmis mooduleid ehk teeked (ingl. library) erinevate probleemide lahendamiseks. Näiteks Matplotlib graafikute loomiseks. NumPy suurte andmemassiivide töötlemiseks. PyTorch masinõppe jaoks. Tkinter graafiliste kasutajaliideste loomiseks ja palju muid.

Markdown

Teksti lahtrites olevat sisu saab kirjutada märgenduskeel Markdown abil. Selle abil saab lihtalt ja kiiresti kirjutada rikalikult vormindatud teksti.

Näiteks pealkirja loomiseks:

Mis on pilt?

Mis on pilt arvuti jaoks? Kuidas on pilt salvestatud arvutis? Kuidas arvutid näevad värve?

Nagu nimigi ütleb, arvutid arvutavad. Ja arvutada saab ainult numbritega. Kõik need YouTube videod, ajalehe artiklid ja kassi pildid on salvestatud arvutisse mingil kujul numbritena.

Kui me suurendame pilti sisse siis näeme, et see koosneb pisikestest ruutudest – pikslitest. Pilti võib vaadata, kui suurt mosaiiki, mis on kokku laotud pisikestest klotsidest. (Pilt 1)

Pikslid

Igas pikslis on kolm numbrit, mis kirjeldavad kolme värvi: punast, rohelist ja sinist. Neid kutsutakse RGB värvideks (Red, Green, Blue). Nendest piisab luua kõik värvitoonid, mida me ekraanil näeme. Iga number on salvestatud 8-bitise arvuna. See tähendab selle väärtus on 0 kuni 255-ni. Kokku 256 erinevat heleduse astet, kus 0 on must ja 255 on valge. Seda võib vaadata nii, et meil on kolme värvi tuled ja me saame muuta iga tule heledust. See number ütleb, kui intensiivne, mingi toon on. Kokku saab moodustada nii 16’777’216 värvitooni (256 * 256 * 256). (Pilt 2)

Värvijaotus halltoonides, punastes, rohelistes ja sinistes kanalites. Vasakul küljel on väärtus 0, paremal 255.

Nüüd võime pilti vaadata, kui ühte suurt Exceli tabelit, kus iga lahter on üks piksel. Tabeli laius ja kõrgus on pildi laius ja kõrgus. Meil on kahedimensiooniline tabel. Kuna ühes lahtris saame hoida ainult ühte arvu. Siis paneme RGB väärtused erinevatesse tabelitesse. Nii, et meil on üks tabeli kiht kus on punane (R), teine kus roheline (G) ja kolmandal sinine (B). Siia võib lisada ka neljanda läbipaistvuse (A), kui meil oleks png fail, mitte jpg. Neid nimetatakse kanaliteks ja mõelda võib neist, kui pildi kolmandast mõõtmest. (Pilt 3)

RGB kanalid

Neid numbreid saame me analüüsida ja teha nendega erinevaid arvutusi.

Näited

Impordime vajalikud teegid (Ing. Library).

import imageio                  # Piltide lugemiseks ja muutmiseks
import matplotlib.pyplot as plt # Skeemide koostamiseks
%matplotlib inline

Kuna kõik mu pildid on selles kataloogis salvestan selle eraldi muutujasse.

#Kõik pildid on siin kataloogis
kataloog = 'https://raw.githubusercontent.com/taunoe/jupyter-notebooks/main/Pildi-anal%C3%BC%C3%BCs/images/'

Kuvame pildi.

pilt = imageio.imread(kataloog + 'image.jpg')
plt.figure(figsize = (5,5))
plt.imshow(pilt)

Pildi info

Loeme põhilised andmed pildi kohta: pildi laius, kõrgus ja kihtide või mõõtmete arv. Kui on RGB pilt siis on 3 (kõrgus, laius, sügavus: RGB) mõõdet. Aga kui halltoonides pilt siis 2 (kõrgus, laius).

print('Pildi kuju (Shape): {}'.format(pilt.shape)) 
print('Pildi kõrgus: {}px'.format(pilt.shape[0])) 
print('Pildi laius: {}px'.format(pilt.shape[1]))
print('Mõõtmete (dimensioonide) arv: {}'.format(pilt.ndim))

Kui on halltoonides (Grayscale) pilt siis saame sellised andmed:

pilt_hall = imageio.imread(kataloog + 'image_hall.jpg')
print('Pildi kuju (Shape): {}'.format(pilt_hall.shape)) 
print('Pildi kõrgus: {}px'.format(pilt_hall.shape[0])) 
print('Pildi laius: {}px'.format(pilt_hall.shape[1]))
print('Mõõtmete arv: {}'.format(pilt_hall.ndim))

Järgmine pilt sisaldab ka läbipaistvuse (Alpha) kanalit.

pilt_alpha = imageio.imread(kataloog + 'image_alpha.png')
print('Pildi kuju (Shape): {}'.format(pilt_alpha.shape)) 
print('Pildi kõrgus: {}px'.format(pilt_alpha.shape[0])) 
print('Pildi laius: {}px'.format(pilt_alpha.shape[1])) 
print('Mõõtmete arv: {}'.format(pilt_alpha.ndim))

Pildi suuruse arvutamine:

print('Pildi suurus on {}'.format(pilt.size))

Suurima ja vähima RGB väärtuse leidmine:

print('Suurim RGB väärtus sellel pildil: {}'.format(pilt.max()))
print('Väikseim RGB väärtus sellel pildil: {}'.format(pilt.min()))

Ühe konkreetse piksli väärtuste vaatamine: piksel real (y-telg) 100 ja tulbas (x-telg) 50:

y = 100
x = 50
print('R kanal: {}'.format(pilt[ y, x, 0]))
print('G kanal: {}'.format(pilt[ y, x, 1]))
print('B kanal: {}'.format(pilt[ y, x, 2]))

Kanalite vaatamine

Vaatame igat pildi RGB kanalit eraldi:’

plt.title('R kanal') 
plt.ylabel('Kõrgus {}'.format(pilt.shape[0])) 
plt.xlabel('Laius {}'.format(pilt.shape[1])) 
plt.imshow(pilt[ : , : , 0])
plt.show()
R kanal
R kanal
plt.title('G kanal') 
plt.ylabel('Kõrgus {}'.format(pilt.shape[0])) 
plt.xlabel('Laius {}'.format(pilt.shape[1])) 
plt.imshow(pilt[ : , : , 1])
plt.show()
plt.title('B kanal') 
plt.ylabel('Kõrgus {}'.format(pilt.shape[0])) 
plt.xlabel('Laius {}'.format(pilt.shape[1])) 
plt.imshow(pilt[ : , : , 2])
plt.show()

Pikslite manipuleerimine

Muudame pildi mingis osas kanalite intensiivsust: Punasel (R) kanalil read 50 kuni 250. Muudame intensiivsuse maksimaalseks (255).

temp_1 = pilt.copy() # teeme pildist koopia
temp_1[50:250 , : , 0] = 255 # full intensity to those pixel's R channel 
plt.figure( figsize = (5,5)) 
plt.imshow(temp_1) 
plt.show()

Rohelisel (G) kanalil, read 250 kuni 450.

temp_1[250:450 , : , 1] = 255 # full intensity to those pixel's G channel 
plt.figure( figsize = (5,5)) 
plt.imshow(temp_1) 
plt.show()

Sinisel kanalil, read 450 kuni 600.

temp_1[450:600 , : , 2] = 255 # full intensity to those pixel's B channel 
plt.figure( figsize = (5,5)) 
plt.imshow(temp_1) 
plt.show()

RGB kanalid erinevatele piltidele

Impordime uue teegi numpy.

import numpy as np

fig, ax = plt.subplots(nrows = 1, ncols=3, figsize=(15,5))  
for c, ax in zip(range(3), ax):     
     # create zero matrix        
     split_img = np.zeros(pilt.shape, dtype="uint8") 
     # 'dtype' by default: 'numpy.float64'  # assing each channel      
     split_img[ :, :, c] = pilt[ :, :, c] # display each channel     
     ax.imshow(split_img)

Halltoonid

Halltoonides pilt on 2 mõõtmeline massiiv (Ing. array). Et viia pilti halltoonidesse peame kuidagi kokku liitma praegu kolmel erineval kihil oleva pildi info. Üks põhjus miks kasutatakse andmetöötluses halltoonides pilte on, et vähendad töödeldavate andmete hulka (1/3 võrreldes täis RGB pildiga). Üks võimalik valem on selleks:

Y′=0.299R+0.587G+0.114B

pilt = imageio.imread(kataloog +'image.jpg') 
gray = lambda rgb : np.dot(rgb[... , :3] , [0.299 , 0.587, 0.114])
gray = gray(pilt)
#plt.figure( figsize = (5,5))  
plt.imshow(gray, cmap = plt.get_cmap(name = 'gray')) 
plt.show()

Lingid