Auteur : Christophe Sinclair
Mail : [email protected]
URL : https://raspberrypi.pagesperso-orange.fr/
Version :4 juin 2020
1. Table des matières 1 Installation ....................................................................................................................................... 5
1.1 Affichage de la version ............................................................................................................................ 5
1.2 Formations .............................................................................................................................................. 5
2 Traitement d’images ........................................................................................................................ 6
2.1 Tableaux Numpy ..................................................................................................................................... 6
2.1.1 Information sur un tableau ............................................................................................................. 6
2.2 Installation des librairies ......................................................................................................................... 7
2.2.1 matplotlib ........................................................................................................................................ 7
2.2.2 pandas ............................................................................................................................................. 7
2.2.3 seaborn et opencv .......................................................................................................................... 8
2.2.4 plotly ............................................................................................................................................. 22
2.2.5 scikit-learn ..................................................................................................................................... 22
2.2.6 scikit-image ................................................................................................................................... 23
2.2.7 bokeh ............................................................................................................................................ 24
2.2.8 dlib ................................................................................................................................................ 25
2.3 Mathplotlib ........................................................................................................................................... 26
2.3.1 Afficher une image à partir d’un fichier ........................................................................................ 26
2.3.2 Animation d’une image créée via le code ..................................................................................... 29
2.3.3 Inverser les composantes RVB BVR ......................................................................................... 30
2.4 Opencv .................................................................................................................................................. 31
2.4.1 Création d’une image à partir d’un tableau numpy ..................................................................... 31
2.4.2 Afficher un fichier image ............................................................................................................... 33
2.4.3 Créer une grande image ............................................................................................................... 36
2.4.4 Déformer une image par une fonction ......................................................................................... 37
2.4.5 Afficher une video ......................................................................................................................... 38
2.4.6 Déformer une vidéo ...................................................................................................................... 40
2.4.7 Changer le font d’une photo ......................................................................................................... 41
2.4.8 Modifier des parties d’image ........................................................................................................ 42
2.4.9 Modifier des parties de photos ..................................................................................................... 43
2.4.10 Dessiner des formes géométriques .............................................................................................. 44
2.4.11 Seuillage des images ..................................................................................................................... 46
2.4.12 Rotation ........................................................................................................................................ 48
2.4.13 Détection de visages dans une photo ........................................................................................... 49
2.4.14 Détection d’image dans une vidéo ............................................................................................... 51
2.5 scikit-image ........................................................................................................................................... 52
2.5.1 Afficher une image ........................................................................................................................ 52
2.6 dlib ........................................................................................................................................................ 53
2.6.1 Afficher une image ........................................................................................................................ 53
2.6.2 Détection de visages dans une photo ........................................................................................... 54
2.6.3 Détection d’image dans une vidéo ............................................................................................... 55
2.6.4 Détection des éléments du visage ................................................................................................ 57
2.7 tkinter + pillow ...................................................................................................................................... 59
2.7.1 Afficher une image ........................................................................................................................ 59
1 Installation Python est déjà préinstallé sur les Raspberry sous Raspberry PI OS.
1.1 Affichage de la version
1.2 Formations Mon but n’est pas de faire un cours de Python pour apprendre les bases. Pour cela, il existe de nombreuses
formations sur Internet.
Les meilleurs formations en français sont certainement celles disponibles sur le site Openclassroom aussi bien
pour l’apprentissage de base du langage, la programmation objet, que sur le web avec les Framework Django
ou Flask.
Python est également très utilisé pour la Data Science et le traitement d’images. Openclassroom contient un
certain nombre de formations sur ces sujets.
- Les bases du graphisme
- La data science
- Les tests
- Traitement d’images
2 Traitement d’images Python contient de nombreuses librairies de traitement d’images pour l’affichage, le traitement de l’image elle
même, mais aussi dans le domaine de l’IA comme la reconnaissance faciale.
Openclassroom présente une formation sur le traitement d’images.
2.1 Tableaux Numpy Numpy permet de gérer des tableaux et de faire beaucoup d’opérations directement sur les éléments du
tableau, là ou en python il faudrait faire des boucles pour modifier chaque élément. Les opérations sont
également beaucoup plus rapides que les tableaux python standards.
Ce type de tableaux est particulièrement adapté au traitement d’images par exemple.
2.1.1 Information sur un tableau import numpy as np
# Création d'une liste à deux dimension de 2*3 éléments
a = ((1, 2, 3), (4, 5, 6))
# Conversion en tableau numpy d'octet
a = np.array(a, dtype=np.uint8)
# type
print('type:', type(a))
# description
print('shape:', a.shape)
# dimension
print('nbytes:', a.nbytes)
# affichage
print('np array:', a)
2.2 Installation des librairies
2.2.1 matplotlib Déjà installé en standard sur le Raspberry
2.2.2 pandas
2.2.3 seaborn et opencv
sudo apt-get install libatlas-base-dev
sudo apt-get install libjasper-dev
sudo apt-get install libqtgui4
sudo apt install libqt4-test
sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev
libpng12-dev
sudo apt-get install libavcodec-dev libavformat-dev
libswscale-dev libv4l-dev
sudo apt-get install libxvidcore-dev libx264-dev
sudo apt-get install libgtk2.0-dev libgtk-3-dev
sudo apt-get install libatlas-base-dev gfortran
Je ne suis pas sûr que tout soit nécessaire, mais ça fonctionne
2.2.4 plotly
2.2.5 scikit-learn
2.2.6 scikit-image
2.2.7 bokeh
2.2.8 dlib
2.3 Mathplotlib Matplotlib est une librairie qui permet d’afficher des images. Ces images pouvant être des fichiers, créés par
programme ou des trames de vidéos.
2.3.1 Afficher une image à partir d’un fichier # Importer la librairie
import matplotlib.pyplot as plt
# Lire le fichier
img = plt.imread('../lena.png')
# Plaquer l'image sur une fenêtre
plt.imshow(img)
# Affiche la fenêtre
plt.show()
Juste pour le fun, la petite histoire de Lena
https://phototrend.fr/2016/07/dessous-images-lenna-icone-informatique-de-playboy/
Sans les graduations
# Importer la librairie
import matplotlib.pyplot as plt
# Lire le fichier
img = plt.imread('../lena.png')
# Plaquer l'image sur une fenêtre
plt.imshow(img)
# Sans graduation
plt.xticks([])
plt.yticks([])
# Affiche la fenêtre
plt.show()
Avec des graduations personnalisées
# Importer les librairies
import matplotlib.pyplot as plt
import numpy as np
# Lire le fichier
img = plt.imread('../lena.png')
# Plaquer l'image sur une fenêtre
plt.imshow(img)
# Graduation
plt.xticks(np.arange(0, 501, step=50))
plt.yticks([50, 150, 250, 350, 450])
# Affiche la fenêtre
plt.show()
2.3.2 Animation d’une image créée via le code import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
k = 2*np.pi
w = 2*np.pi
dt = 0.01
xmin = 0
xmax = 3
nbx = 100
x = np.linspace(xmin, xmax, nbx)
fig = plt.figure() # initialise la figure
line, = plt.plot([],[])
plt.xlim(xmin, xmax)
plt.ylim(-1,1)
# fonction à définir quand blit=True
# crée l'arrière de l'animation qui sera présent sur chaque image
def init():
line.set_data([],[])
return line,
def animate(i):
t = i * dt
y = np.cos(k*x - w*t)
line.set_data(x, y)
return line,
ani = animation.FuncAnimation(fig, animate, init_func=init, frames=100, blit=True, interval=20,
repeat=True)
plt.show()
2.3.3 Inverser les composantes RVB BVR import matplotlib.pyplot as plt
img = plt.imread('../lena.png')
img = img[:,:,[2,1,0]] # BGR to RGB
plt.imshow(img)
plt.xticks([]) # no graduations
plt.yticks([])
plt.show()
2.4 Opencv Opencv est une librairie graphique spécialisée dans le traitement d’images
Pour que les programmes utilisant cette librairie fonctionnent, il faut pré-charger une librairie avec la
commande :
LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1
2.4.1 Création d’une image à partir d’un tableau numpy import cv2 as cv
import numpy as np
img = (
(( 0, 0, 0), (128, 128, 128), (255, 255, 255)),
(( 0, 0, 255), ( 0, 255, 0), (255, 0, 0)),
((255, 255, 0), ( 0, 255, 255), (255, 0, 255)))
img = np.array(img, dtype=np.uint8)
cv.imshow('win', img)
cv.waitKey()
cv.destroyAllWindows()
Cela devrait créer une image de seulement 6 pixels, mais l’affichage est automatiquement zoomé pour être
visible.
La commande « waitKey » sans paramètre attend l’appui sur une touche indéfiniment. Vous pouvez également
mettre une temporisation en milliseconde.
Attention : « waitKey(0) » bloque le programme. Cette commande semble de toute façon très capricieuse sur le
Raspberry.
Le même programme avec un zoom
import cv2 as cv
import numpy as np
img = (
(( 0, 0, 0), (128, 128, 128), (255, 255, 255)),
(( 0, 0, 255), ( 0, 255, 0), (255, 0, 0)),
((255, 255, 0), ( 0, 255, 255), (255, 0, 255)))
img = np.array(img, dtype=np.uint8)
cv.namedWindow('win', cv.WINDOW_NORMAL)
scale = 60
height, width = img.shape[:2]
cv.resizeWindow('win', width*scale, height*scale)
cv.imshow('win', img)
cv.waitKey()
cv.destroyAllWindows()
2.4.2 Afficher un fichier image Image en png
import cv2 as cv
img = cv.imread('../lena.png')
cv.imshow('win', img)
cv.waitKey()
cv.destroyAllWindows()
Image en jpg
import cv2 as cv
img = cv.imread('lenafull.jpg')
cv.imshow('win', img)
cv.waitKey(0)
cv.destroyAllWindows()
Image en bmp, même avec seulement 2 couleurs
2.4.3 Créer une grande image import cv2 as cv
import numpy as np
sx, sy = 1200, 800
img = np.empty((sy, sx, 3), dtype=np.uint8)
color1 = 255, 0, 0
color2 = 0, 255, 0
color3 = 0, 0, 255
compteur = 0
for y in range(sy):
for x in range(sx):
if compteur % 3 == 0:
img[y, x] = color1
if compteur % 3 == 1:
img[y, x] = color2
if compteur % 3 == 2:
img[y, x] = color3
compteur += 1
cv.imshow('win', img)
cv.waitKey(0)
Cette image met environ 7s à s’afficher, ce fonctionnement est particulièrement inefficace.
2.4.4 Déformer une image avec une fonction import cv2 as cv
import numpy as np
def f(x, y):
"""Reverse mapping function."""
d = (x**2 + y**2)**0.5
return x*d, y*d
img1 = cv.imread('lena.png')
sy, sx = img1.shape[:2]
img2 = np.zeros((sy, sx, 3), dtype=np.uint8)
cx, cy = (sx-1)/2, (sy-1)/2
for y2 in range(sy):
dy2 = 1 - y2/cy
for x2 in range(sx):
dx2 = x2/cx - 1
dx1, dy1 = f(dx2, dy2)
x1 = round(cx*(dx1 + 1))
y1 = round(cy*(1 - dy1))
if (0 <= x1 < sx) and (0 <= y1 < sy):
img2[y2, x2] = img1[y1, x1]
cv.imshow('win', img2)
cv.waitKey(0)
2.4.5 Afficher une video A partir d’un fichier
import cv2 as cv
capture = cv.VideoCapture('VID_20200521_190725.mp4')
fps = capture.get(cv.CAP_PROP_FPS)
delay = round(1000/fps)
while True:
ret, frame = capture.read()
if not ret: # end of file
break
cv.imshow('win', frame)
key = cv.waitKey(delay)
if key == 27: # ESC
break
capture.release()
cv.destroyAllWindows()
A partir d’une webcam (Microsoft LifeCam sur USB)
import cv2 as cv
capture = cv.VideoCapture(0)
fps = capture.get(cv.CAP_PROP_FPS)
delay = 1
while True:
ret, frame = capture.read()
if not ret: # end of file
break
cv.imshow('win', frame)
key = cv.waitKey(delay)
if key == 27: # ESC
break
capture.release()
cv.destroyAllWindows()
2.4.6 Déformer une vidéo import cv2 as cv
import numpy as np
def f(x, y):
"""Reverse mapping function."""
d = (x**2 + y**2)**0.3
return x*d, y*d
capture = cv.VideoCapture('VID_20200521_193521.mp4')
fps = capture.get(cv.CAP_PROP_FPS)
delay = round(1000/fps)
while True:
ret, frame = capture.read()
if not ret: # end of file
break
sy, sx = frame.shape[:2]
img2 = np.zeros((sy, sx, 3), dtype=np.uint8)
cx, cy = (sx-1)/2, (sy-1)/2
for y2 in range(sy):
dy2 = 1 - y2/cy
for x2 in range(sx):
dx2 = x2/cx - 1
dx1, dy1 = f(dx2, dy2)
x1 = round(cx*(dx1 + 1))
y1 = round(cy*(1 - dy1))
if (0 <= x1 < sx) and (0 <= y1 < sy):
img2[y2, x2] = frame[y1, x1]
cv.imshow('win', img2)
#cv.imshow('win1', frame)
key = cv.waitKey(delay)
if key == 27: # ESC
break
capture.release()
cv.destroyAllWindows()
Ça marche, mais c’est très lent (une image toutes les 10s)
2.4.7 Changer le font d’une photo import cv2
# Read the images
foreground = cv2.imread("photo.png")
background = cv2.imread("papier-japonais-fibre-blanche-fond-blanc-63x97.jpg")
alpha = cv2.imread("filtre2.png")
# Convert uint8 to float
foreground = foreground.astype(float)
background = background.astype(float)
# Normalize the alpha mask to keep intensity between 0 and 1
alpha = alpha.astype(float)/255
# Multiply the foreground with the alpha matte
foreground = cv2.multiply(alpha, foreground)
# Multiply the background with ( 1 - alpha )
background = cv2.multiply(1.0 - alpha, background)
# Add the masked foreground and background.
outImage = cv2.add(foreground, background)
# Display image
cv2.imshow("outImg", outImage/255)
cv2.waitKey(0)
2.4.8 Modifier des parties d’image import cv2 as cv
import numpy as np
def replace(img1, img2, x, y):
h2, w2 = img2.shape[:2]
img1[y:y+h2, x:x+w2, :] = img2
img2 = np.array(
(((0, 0, 255),(0, 255, 0)),
((255, 0, 0),(255, 255, 255))),
np.uint8)
for i in range(0, 20):
img1 = np.zeros((5, 5, 3), np.uint8)
replace(img1, img2, x=i%2 + 1, y=i%2 + 1)
cv.namedWindow('win', cv.WINDOW_NORMAL)
scale = 60
h1, w1 = img1.shape[:2]
cv.resizeWindow('win', w1*scale, h1*scale)
cv.imshow('win', img1)
cv.waitKey(300)
cv.waitKey(1000)
cv.destroyAllWindows()
2.4.9 Modifier des parties de photos import cv2 as cv
import numpy as np
def replace(img1, img2, x, y):
h2, w2 = img2.shape[:2]
img1[y:y+h2, x:x+w2, :] = img2
photo = cv.imread("../lena.png")
img2 = photo[200:300, 200:300]
for i in range(0, 400):
img1 = np.copy(photo);
replace(img1, img2, x=i, y=i)
cv.namedWindow('win', cv.WINDOW_NORMAL)
cv.imshow('win', img1)
cv.waitKey(20)
cv.waitKey(1000)
cv.destroyAllWindows()
2.4.10 Dessiner des formes géométriques Opencv permet de dessiner des formes géométriques.
import numpy as np
import cv2 as cv
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (0, 255, 255)
ORANGE = (0, 165, 255)
RED = (0, 0, 255)
RASPBERRY = (92, 11, 227)
BROWN = (42, 42, 165)
GREEN = (0, 255, 0)
CYAN = (255, 255, 0)
BLUE = (255, 0, 0)
MAGENTA = (255, 0, 255)
PURPLE = (128, 0, 128)
img = np.zeros((500, 500, 3), np.uint8)
for i in range (0, 500, 50):
cv.line(img, pt1=(i, 0), pt2=(i, 500), color=BLUE, thickness=2, lineType=cv.LINE_AA)
cv.line(img, pt1=(0, i), pt2=(500, i), color=BLUE, thickness=2, lineType=cv.LINE_AA)
cv.rectangle(img, pt1=(25, 25), pt2=(475, 475), color=RED)
cv.rectangle(img, pt1=(75, 75), pt2=(425, 425), color=ORANGE)
cv.rectangle(img, pt1=(125, 125), pt2=(375, 375), color=YELLOW)
cv.rectangle(img, pt1=(175, 175), pt2=(325, 325), color=BROWN)
cv.rectangle(img, pt1=(225, 225), pt2=(275, 275), color=GREEN)
cv.rectangle(img, pt1=(25, 25), pt2=(475, 475), color=MAGENTA)
cv.drawMarker(img, (250, 250), WHITE , cv.MARKER_DIAMOND, markerSize=25, thickness=2)
cv.circle(img, center=(50, 50), radius=20, color=BLACK, thickness=cv.FILLED)
cv.circle(img, center=(250, 250), radius=125, color=PURPLE)
poly = np.array(((250,25), (475, 250), (250, 475), (25, 250)), np.int32)
cv.polylines(img, pts=[poly], isClosed=True, color=RASPBERRY, thickness=2, lineType=cv.LINE_AA)
cv.putText(img, text='Raspberry', org=(200, 200), fontFace=cv.FONT_HERSHEY_SIMPLEX,
fontScale=1.5, color=PURPLE, thickness=2, lineType=cv.LINE_AA)
cv.imshow('win', img)
cv.waitKey()
cv.destroyAllWindows()
2.4.11 Seuillage des images Opencv permet des seuillages sur les images.
import numpy as np
import cv2 as cv
img = cv.imread('sudoku.png', cv.IMREAD_GRAYSCALE)
img = cv.medianBlur(img, 5)
img = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 11, 3)
cv.imshow('win', img)
cv.waitKey()
cv.destroyAllWindows()
2.4.12 Rotation import cv2 as cv
import numpy as np
def replace(img1, img2, x, y):
h2, w2 = img2.shape[:2]
img1[y:y+h2, x:x+w2, :] = img2
photo = cv.imread("../lena.png")
for i in range(0, 360):
transfoMatrix = cv.getRotationMatrix2D((photo.shape[0] / 2, photo.shape[1] / 2), i, 0.8)
newImg = cv.warpAffine(photo, transfoMatrix, None,
flags = cv.INTER_LINEAR,
borderMode = cv.BORDER_REFLECT)
cv.namedWindow('win', cv.WINDOW_NORMAL)
cv.imshow('win', newImg)
cv.waitKey(5)
cv.waitKey(1000)
cv.destroyAllWindows()
2.4.13 Détection de visages dans une photo Télécharger tout d’abord le fichier « harrcascade_frontalface.xml » sur le projet opencv de github.
Il y a également d’autres fichiers qui permettent de détecter d’autres choses, comme les yeux ou des chats.
import cv2 as cv
import math
IMAGE = 'gettyimages-200244519-007-1024x1024.jpg'
def detect_faces(classifier, img):
RED = (0, 0, 255)
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
faces = classifier.detectMultiScale(img_gray)
for x, y, w, h in faces:
cv.circle(img, center = (math.floor(x + w / 2), math.floor(y + h / 2)), radius = math.trunc(h /
2), color=RED, thickness=2)
classifier = cv.CascadeClassifier('haarcascade_frontalface.xml')
img = cv.imread(IMAGE)
detect_faces(classifier, img)
cv.imshow('win', img)
cv.waitKey(0)
cv.destroyAllWindows()
Cela détecte les visages de face, droit et pas trop important sur l’image (c’est pour cela que la personne au
premier plan n’est pas détectée)
2.4.14 Détection d’image dans une vidéo import cv2 as cv
import math
def detect_faces(classifier, img):
RED = (0, 0, 255)
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
faces = classifier.detectMultiScale(img_gray)
for x, y, w, h in faces:
cv.circle(img, center = (math.floor(x + w / 2), math.floor(y + h / 2)), radius = math.trunc(h /
2), color=RED, thickness=2)
capture = cv.VideoCapture('videofoot.mp4')
fps = capture.get(cv.CAP_PROP_FPS)
delay = round(1000/fps)
classifier = cv.CascadeClassifier('haarcascade_frontalface.xml')
while True:
ret, frame = capture.read()
detect_faces(classifier, frame)
if not ret: # end of file
break
cv.imshow('win', frame)
key = cv.waitKey(delay)
if key == 27: # ESC
break
capture.release()
cv.destroyAllWindows()
C’est franchement saccadé, mais ça marche, même si il y a beaucoup de non détections et de fausses détections.
2.5 scikit-image
2.5.1 Afficher une image import skimage.io
img = skimage.io.imread('../lena.png')
skimage.io.imshow(img)
skimage.io.show()
2.6 dlib
2.6.1 Afficher une image import dlib
img = dlib.load_rgb_image('../lena.png')
win = dlib.image_window()
win.set_image(img)
Ne pas oublier l’option –i sinon le programme s’arrête tout de suite
2.6.2 Détection de visages dans une photo import face_recognition
import matplotlib.pyplot as plt
IMG = 'gettyimages-200244519-007-1024x1024.jpg'
#----- load and display image
img = face_recognition.load_image_file(IMG)
plt.xticks([])
plt.yticks([])
plt.imshow(img)
#----- detect faces
faces = face_recognition.face_locations(img, model='hog')
#----- show detections
for y0, x1, y1, x0 in faces:
x = x1, x0, x0, x1, x1
y = y0, y0, y1, y1, y0
plt.plot(x, y, color='lime')
plt.show()
2.6.3 Détection d’image dans une vidéo import cv2 as cv
import face_recognition
#------------------------------------------------------------------------------
def detect_faces(img):
faces = face_recognition.face_locations(img[:,:,::-1])
for y0, x1, y1, x0 in faces:
cv.rectangle(img, (x0, y0), (x1, y1), (255,0,0), 2)
#------------------------------------------------------------------------------
def get_image():
capture = cv.VideoCapture('videofoot.mp4')
while True:
ret, img = capture.read()
if not ret:
break
yield img
key = cv.waitKey(1)
if key == 27:
break
capture.release()
#------------------------------------------------------------------------------
if __name__ == '__main__':
for img in get_image():
detect_faces(img)
cv.imshow('win', img)
cv.destroyAllWindows()
Ça fonctionne, mais c’est extrêmement lent
2.6.4 Détection des éléments du visage import face_recognition
import matplotlib.pyplot as plot
image = face_recognition.load_image_file('gettyimages-200244519-007-1024x1024.jpg')
plot.xticks([])
plot.yticks([])
plot.imshow(image)
visages = face_recognition.face_landmarks(image)
COLORS = {'chin': 'orange', # menton
'left_eyebrow': 'green', # sourcil gauche
'right_eyebrow': 'green', # sourcil droit
'nose_bridge': 'yellow', # arête du nez
'nose_tip': 'yellow', # trous de nez
'left_eye': 'blue', # oeil gauche
'right_eye': 'blue', # oeil droit
'top_lip': 'red', # lèvre haute
'bottom_lip': 'magenta'} # lèvre basse
for visage in visages:
for element, pts in visage.items():
x = tuple(p[0] for p in pts)
y = tuple(p[1] for p in pts)
plot.plot(x, y, color=COLORS[element])
plot.show()
2.7 tkinter + pillow
2.7.1 Afficher une image import tkinter as tk, numpy as np, PIL.Image, PIL.ImageTk
img = PIL.Image.open('../lena.png')
w, h = img.size
win = tk.Tk()
win.geometry(f'{w+20}x{h+20}')
win.resizable(False, False)
img = PIL.ImageTk.PhotoImage(image=img)
lbl = tk.Label(win, image=img)
lbl.place(x=8, y=8)
win.mainloop()
En GIF, plus pixélisé car le format ne gère que 256 couleurs
import tkinter as tk, numpy as np, PIL.Image, PIL.ImageTk
img = PIL.Image.open('../lena.gif')
w, h = img.size
win = tk.Tk()
win.geometry(f'{w+20}x{h+20}')
win.resizable(False, False)
img = PIL.ImageTk.PhotoImage(image=img)
lbl = tk.Label(win, image=img)
lbl.place(x=8, y=8)
win.mainloop()