convolution.py (linux seulement)

text/x-python convolution.py — 5.9 KB

Contenu du fichier

#!/usr/bin/env python
#  convolution.py
#-------------------
# Ce programme implante un calcul de convolution sur une image en utilisant les processu
# Le filtre utilisé est un filtre moyenneur.
# Le programme ne fonctionne que sur des images de type «raw»
#
# Paramètres sur la lignre de commandes
#  - Parm #1 : nombre de fils à utiliser
#  - Parm #2 : taille «horizontale» de l'image 
#  - Parm #3 : taille «verticale» de l'image 
#  - Parm #4 : nom du fichier contenant l'image
#  - Parm #5 : nom du fichier de sortie
#  - Parm #6 : taille du filtre
import sys
import time
from datetime import datetime
import numpy as np
from ctypes import *
import struct
from multiprocessing import Process, Value, Array
from multiprocessing import  shared_memory
import ctypes

# Fonction convolution
# Cette fonction calcule la convolution pour un certain nombre de points
# d'une image
#
# Entrée : index - identificateur du fil 
#          taille : taille de la partie de l'image à traiter (en 1D)
#          filtre : le filtre à appliquer sur l'image
#          taille_filtre : la dimension du filtre
#          image : l'image à traiter (emmagasinée dans un tableau 1D)
#          tx : la dimension en «x» de l'image (nb lignes)
#          ty : la taille en «y» de l'image  (nb colonnes) 
# Sortie  : sortie : image modifiée
#
def convolution(index, taille, filtre, taille_filtre, image, tx, ty, sortie):
    
    dis = int(taille_filtre/2)   # on calcule la distance à traiter autour du pixel
    #----------------------------------------------------------------------
    # Chaque fil (noyau) traite une partie de l'image de taille «taille».  
    # Selon l'index du fil on détermine quelle partie le fil doit traiter   
    debut = int(taille*index)
    fin1 = int(debut + taille) 
    #----------
    # ****** impression pour mise au point ***************
    print("Fil", index, " debute a ", debut, " jusqu'a ", fin1-1, " --> " ,int(debut/tx),",",debut%tx , " -- ",int((fin1-1)/tx),",",(fin1-1)%tx)
    #-------------------------------------------------------------------------
    # On parcourt l'image pour traiter chaque pixel
    for indice  in range(debut,fin1):
        # L'image est emmagasinée dans un tableau 1D.
        # Selon la taille de l'image on se repositionne en 2D (ligne et colonne)
        ligne  = int(indice/ty)
        col = int(indice%tx)
        res=0.0;
        #-------------------------------------------------------------------
        # Application du filtre sur le pixel
        for i in range(0, taille_filtre):
             for j in range(0,taille_filtre):
                 indice1 = ligne - dis + i;         #indice pour la ligne
                 indice2 = col - dis + j ;          # indice pour la colonne
                 if indice1 < 0  : indice1 = 0      # au cas où l'indice soit à l'extérieur de l'image
                 if indice2 < 0  : indice2 = 0      # au cas où l'indice soit à l'extérieur de l'image
                 if indice1 > tx-1 : indice1 = tx-1     # au cas où l'indice soit à l'extérieur de l'image
                 if indice2 > ty-1 : indice2 = ty-1     # au cas où l'indice soit à l'extérieur de l'image
                 # Application du filtre et cumul du résultat
                 res += np.uint8(image[indice1*tx + indice2]) * filtre;
                 # ****** Possible impression pour mise au point
                 #print("Resultats = ", indice1, " - ", indice2, " pixel ", int(image[indice1*tx + indice2]), " --> ",  np.uint8(res))
        # sauvegarde du résultat dans l'image de sortie
        sortie[ligne*tx + col]= np.uint8(res)

#*********************************************************************
#   Programme pincipal qui prépare le calcul et le lance
# **********************************************************************

if __name__=="__main__":
   
    # Récupération des paramètres
    nbFils = eval(sys.argv[1])
    th_image = eval(sys.argv[2])
    tv_image = eval(sys.argv[3])
    nom = str(sys.argv[4])
    nom_sortie = str(sys.argv[5])
    taille_filtre = eval(sys.argv[6])
   
    # Lecture de l'image
    f = open(nom, mode = "rb")
    texte = f.read()   
    taille_texte= len(texte) 
    print(taille_texte)
    print(texte[taille_texte-1])
    # Avec le multi-processus, il n'y a pas de mémoire commune implicite
    # Il faut donc explictement se décalrer de la mémoire partagée
    # Déclaration d'yune zone de mémoire partagée pour le fichier de sortie
    shm = shared_memory.SharedMemory(create=True, size=taille_texte)
    type(shm.buf)
    sortie = shm.buf
    # Calcul de la valeur du filtre moyenneur
    filtre = 1.0/ (taille_filtre * taille_filtre);
    #-------
    # On détermine la dimension de l'image à traiter par chaque fil (ou coeurs)
    # le dernier fil traite aussi les pixels «restant»
    temp = taille_texte / nbFils;
    temp2 = temp + (taille_texte % nbFils)
    # -----
    # Positionnement du chronomètre pour évaluer la performance
    debut = datetime.now()
    # ----
    # Démarrage des processus 
    processus = []
    for n in range(0, nbFils):
        if n < nbFils-1 : p = Process(target=convolution, args=(n, temp, filtre, taille_filtre, texte, th_image, tv_image, sortie))
        else : p = Process(target=convolution, args=(n, temp2, filtre, taille_filtre, texte, th_image, tv_image, sortie))
        processus.append(p)
        p.start()
    # Attente de la fin d'exécution des processus
    for p in processus:
        p.join()
    #===============================================
    # Arrêt du chronomètre
    fin = datetime.now()
    # Sauvegarde du résultat dans fichier de sortie
    f = open(nom_sortie, mode = "wb")
    f.write(sortie)
    #----------------
    # Affichage du temps d'exécution
   
    delta = fin -debut
    print("temps d'exécution en secondes = ", delta.total_seconds())
    shm.close()
    shm.unlink()