Py: remake projet p1
Py: remake projet p1

remake du projet p1

Directory

Repo

Classe ProcessImg

Traitement de l’image

Dans le fichier processIng.py, la classe ProcessImg se charge de traiter l’image à l’aide d’openCV.

  • Assignation de l’attribut self.original qui contient l’image originale sous forme de liste numpy. Chaque elément contient une liste contenant un $x$ un $y$ et une valeur référence de la couleur.

  • Les attributs self.height et self.width contiennent repectivement la largeur et la longueur totale de l’image originiale calculés à partir de la methode shape de l’objet self.original

  • self.processed contient un appel de la methode __process() qui se charge d’appliquer le traitement à l’image.

def __process(self):
    img    = cv2.cvtColor(self.original, cv2.COLOR_BGR2GRAY)
    img    = cv2.GaussianBlur(img, (3, 3), 0)
    # img  = cv2.Canny(img, 50, 220)
    img    = cv2.Canny(img, 100, 200)
    # kernel = np.ones((2, 2), np.uint8)
    # img  = cv2.dilate(img, kernel, iterations = 1)
    # img  = cv2.erode(img, kernel, iterations  = 1)
    img  = self.resize(img)
  1. Transformations des couleurs en dégradé de gris.
  2. Application d’un flou gaussien pour adoussir les bords.
  3. Application de l’algorithme Canny edges qui detecte les bords et ne garde que ces derniers. Hyrestesis set sur 100/200
  4. Un resize pour les images plus grandes que 640px (déterminer une valeur optimale)
     def resize(self, img, width=640):
         if self.width > 640:
             img_scale = width / self.width
             xx = int(self.original.shape[1] * img_scale)
             yy = int(self.original.shape[0] * img_scale)
             self.height, self.width = yy, xx
             resized = cv2.resize(img, (xx, yy))
             return resized
    
  5. Est retourné à l’attribut self.processed la detection de bords redimensionnée et à laquelle on ajoute un padding via la méthode padding() pour éviter les overflow lors de la recherche de points par la suite.
         def padding(self, canny):
         return cv2.copyMakeBorder(
             canny, 100, 100, 100, 100, 
             cv2.BORDER_CONSTANT, value=0000)
    

Optionnel: les lignes commentées dans __process() permettent d’appliquer un traitement qui vise a fermer les bords incomplets de certaines images. Très efficace pour certaines images, induit cependant une perte de qualité massive dans d’autres.

Affichage

La methode self.display() permet d’afficher l’image après process. Elle fait appel à plusieurs methodes d’openCV pour controler la fenêtre d’affichage.

classe Grid

Dans le fichier processImg.py, la class Grid se charge de traiter une liste 2d qui sort de la classe ProcessImg pour la mettre sous forme de liste 1d.

Elle devrait également gérer toute la logique pour permettre d’utiliser cette liste comme si l’image était sous forme d’une liste 2d. A réfléchir

  • self.img contient un objet de type ProcessImg auquel est passé l’image reçu en argument lors de l’instanciation d’un objet de type Grid
  • self.canny contient un numpy array des points composant les bords de l’image contenue dans self.img.
  • self.len contient le nombre de points composant self.canny
  • self.height, self.width contiennent une vision logique du format des points contenu dans self.canny

bin_list

Cette methode retourne un bytearray contenant les points de l’image après traitement par la methode __process() de la classe ProcessgImg.

Traitement liste de points

Solution 1 (depreciated)

En sortie de la méthode coords() de la classe ProcessImg les points sont classés ligne par ligne dans une liste. Chaque ligne est référencée par un pixel de l’axe y de notre image.

Il faut faire en sorte que le dessin soit fluide et ressemble à la façon de dessiner d’un humain et non pas à celle d’une imprimante. En gros, il nous faut Trouver une ligne qui connecte tous les points de la liste.

Shortest path problem in a graph, where:

  1. the graph nodes are the points in the space,
  2. each node is connected to its 2 nearest neighbors, and
  3. the shortest path passes through each of the nodes only once. That last constrain is a very important (and quite hard one to optimize).

Solution 2

Conversion image

Trouver les points d’intersection de deux cercles (angle du bras)

alt

Liste de points (solution obsolete, openCV is the go!)

from PIL import Image
import tkinter as tk

i = Image.open("aa.png")

pixels = i.load()
width, height = i.size

coords = []

for x in range(width):
    for y in range(height):
        cpixel = pixels[x, y]
        bw_value = int(round(sum(cpixel) / float(len(cpixel))))
        if bw_value != 255:
            # (x, y, (r,g,b))
            coords.append((x, y, cpixel))

canvas_width  = width
canvas_height = height

master = tk.Tk()

w = tk.Canvas(master, width=canvas_width, height=canvas_height)

w.pack()

for i in coords:
    x1, y1 = i[0] - 1, i[1] - 1
    x2, y2 = i[0] + 1, i[1] + 1
    w.create_oval(x1, y1, x2, y2, fill="black")
    

tk.mainloop()

Variantes

monochrome

cpixel = pixels[x, y]
bw_value = int(round(sum(cpixel) / float(len(cpixel))))
# the above could probably be bw_value = sum(cpixel)/len(cpixel)
all_pixels.append(bw_value)

luminance (weighted average)

cpixel = pixels[x, y]
luma = (0.3 * cpixel[0]) + (0.59 * cpixel[1]) + (0.11 * cpixel[2])
all_pixels.append(luma)

pure 1-bit black and white

cpixel = pixels[x, y]
if round(sum(cpixel)) / float(len(cpixel)) > 127:
    all_pixels.append(255)
else:
    all_pixels.append(0)