J'ai fait une sorte d'outil de traitement d'image simple en langage Go.

Je suis un débutant en langue Go. Mon habitat habituel est JS / TS + Java, mais j'essaie le langage Go à partir de cette année parce que je veux être meilleur dans le traitement des langages côté serveur. La raison de ce défi est «des activités modernes, multi-threadées et liées aux conteneurs».

Après tout, le style de faire quelque chose et d'apprendre ça me convient, donc cette fois avec le thème du "traitement d'image", un outil qui peut être utilisé à la fois comme CLI et comme API yellow-high5 / pictar J'ai fait (: //github.com/yellow-high5/pictar). Le traitement d'image n'est pas aussi avancé que l'utilisation de CNN pour la reconnaissance d'image.

Aller au package d'images standard

Tout d'abord, j'ai brièvement vérifié le fonctionnement du paquet d'images standard Go.

Point,Rectangle

Le point de coordonnées Point est composé de X et Y de int, et la zone rectangulaire Rectangle est composée de Min et Max de Point.

image.png

Color

--Alpha ... Transparence --CMYK ... Comment exprimer les couleurs affichées en cyan, magenta, jaune et noir (Key Plate) --RGB ... Comment exprimer les couleurs affichées en rouge, vert et bleu --Gray .. Si l'échelle de gris est RVB, les trois valeurs seront identiques.

image.NRGBA Dans cette structure, l'image est traitée comme un tableau unidimensionnel ** qui répète ** Rouge, Vert, Bleu, Alpha avec «Pix». «Stride» signifie ** la taille d'une ligne horizontale de l'image **.

image.png

Lire la bibliothèque d'imagerie

Les personnes qui ne sont pas spécialisées dans le traitement d'images ne peuvent pas comprendre les formules difficiles, nous utilisons donc des bibliothèques. Cette fois, nous utiliserons désintégration / imagerie. La source elle-même est également concise et facile à lire. Les fonctions peuvent être les suivantes.

Traitement d'image

--adjust ... Échelle de gris, inversion, contraste, saturation --convolution ... compression 3x3, compression 5x5 --effets ... Flou, net --matrix (histogramme normalisé) ... Exprime la luminosité dans un tableau de 256 (16x16) --resize ... redimensionner, recadrer, mettre à l'échelle (ajustement), vignette --transformer ... Retourner, Transposer, Faire pivoter

Utilitaire auxiliaire

--io ... Lire l'image, ouvrir l'image, écrire l'image, enregistrer l'image, lire l'orientation de l'image (drapeau EXIF), convertir, modifier --scanner ... Lit la zone spécifiée par le rectangle --tools ... Créer une nouvelle image, copier, coller, transparente --utils ... parallèle, autres utilitaires

Extra: Glossaire du traitement d'image

J'ai senti qu'il était nécessaire de comprendre certains termes de traitement d'image pour en faire un outil, donc j'organiserai mes connaissances.

  • Espace colorimétrique HSV ... Teinte, Saturation Un espace de composants composé de (Saturation) et de luminosité (Valeur). Il semble être plus intuitif et facile à comprendre que l'espace RVB, qui est déterminé par le mélange de couleurs primaires.
  • Espace colorimétrique HLS ... Teinte, Luminosité ( Un espace de composants composé de trois composants: Luminosité et Saturation Similaire à l'espace HSV.
  • Saturation ... Image supérieure plus sombre, couleur d'image inférieure Image qui s'amincit.
  • [Contraste](https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E3%83%88%E3%83%A9%E3%82%B9%E3 % 83% 88 #% E5% 86% 99% E7% 9C% 9F% E6% A9% 9F% E3% 80% 81% E6% 98% A0% E5% 83% 8F% E6% A9% 9F% E5% 99% A8) ... Lorsqu'elle est élevée, la différence de luminosité de l'image est nette, et lorsqu'elle est faible, l'image est floue.
  • Luminosité ... Image qui devient blanchâtre lorsqu'elle est haute et noirâtre lorsqu'elle est basse.
  • Correction gamma ... proportion simple Une méthode de correction RVB qui correspond aux caractéristiques visuelles humaines, pas à la relation.
  • [Flou gaussien](https://ja.wikipedia.org/wiki/%E3%82%AC%E3%82%A6%E3%82%B7%E3%82%A2%E3%83%B3% E3% 81% BC% E3% 81% 8B% E3% 81% 97) ... La valeur sigma correspond à la quantité de flou.
  • [Fonction Sigmaid](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%B0%E3%83%A2%E3%82%A4%E3%83%89% E9% 96% A2% E6% 95% B0) ... En Deep Learning, c'était une fonction familière de calculer "la probabilité que le nombre écrit dans cette image soit 1", mais en traitement d'image, contraste Il semble qu'il sert à s'ajuster.

Traitement parallèle

désintégration / imagerie utilise un traitement parallèle lors du traitement des images. Cela semble permettre un traitement relativement rapide. Certaines personnes mesurent la vitesse de traitement de l'image, donc si vous voulez en savoir plus à ce sujet, je pense que vous devriez vous y référer.

Comparaison des performances de traitement d'image en langage OpenCV, GoCV, Go-ZOZO Technologies TECH BLOG

Alors, quel type de traitement parallèle est effectué par goroutine dans cette bibliothèque? L'indice était dans la fonction parallèle ci-dessous.

imaging/utils.go


// parallel processes the data in separate goroutines.
func parallel(start, stop int, fn func(<-chan int)) {
	count := stop - start
	if count < 1 {
		return
	}

	procs := runtime.GOMAXPROCS(0)
	limit := int(atomic.LoadInt64(&maxProcs))
	if procs > limit && limit > 0 {
		procs = limit
	}
	if procs > count {
		procs = count
	}

	c := make(chan int, count)
	for i := start; i < stop; i++ {
		c <- i
	}
	close(c)

	var wg sync.WaitGroup
	for i := 0; i < procs; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			fn(c)
		}()
	}
	wg.Wait()
}

** count ** est le nombre d'opérations à effectuer. Dans le cas du traitement d'image, cela correspond au nombre de pixels et à une ligne horizontale d'images. ** procs ** est le nombre de processus à exécuter simultanément. (La valeur par défaut est le nombre de processeurs. Si vous spécifiez le nombre de goroutines à traiter simultanément avec ** limit **, la limite est adoptée.)

Le nombre de valeurs d'entrée est envoyé au canal, et le nombre de procs de goroutine reçoit la valeur d'entrée du canal et la traite en parallèle avec la fonction transmise.

Vous trouverez ci-dessous un tableau montrant comment imaging.FlipH (le processus consistant à inverser la gauche et la droite d'une image) traite en parallèle et la produit. J'ai essayé de dessiner une image.

image.png

Le code qui réalise l'image ci-dessus


func FlipH(img image.Image) *image.NRGBA {
	src := newScanner(img)
	dstW := src.w
	dstH := src.h
	rowSize := dstW * 4
	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
    //Faites travailler en parallèle autant que la hauteur de l'image
	parallel(0, dstH, func(ys <-chan int) {
        //Inverser le groupe de pixels pour une ligne
		for dstY := range ys {
            //Placez chaque pixel à l'endroit au moment de l'inversion
			i := dstY * dst.Stride
			srcY := dstY
			src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
			reverse(dst.Pix[i : i+rowSize])
		}
	})
	return dst
}

Outil CLI avec cobra

Enveloppez ces bibliothèques et créez une CLI en utilisant cobra. Tout d'abord, lors de la conception d'une CLI, identifions les sous-commandes et les options à exécuter par cette commande. Vous devriez également envisager de rendre les options applicables globalement.

Fondamentalement, il est créé avec le modèle de générateur dans le modèle de conception. En tant que référence pour le design, il est également traité dans les réalisations de cobra, mais j'ai essayé d'imiter Hugo.

hugo/commands GitHub

Dans Hugo, lors de la définition d'une sous-commande, définissez-la comme suit.

Lors de la définition d'une sous-commande appelée "hoge"


package commands


//La structure définit les options
type hogeCmd struct {
  *baseBuilderCmd

  /*Options d'écriture*/
  ...
}

//Retour des options dans Command Builder
func (b *commandsBuilder) newHogeCmd() *hogeCmd {
  //Définir une interface vide facultative
  cc := &hogeCmd{}
  
  //Définition de commande avec cobra
  cmd := &cobra.Command{
		Use:   "hoge",
		Short: "Short Description",
		Long: `Long Description`,
    RunE: func(cmd *cobra.Command, args []string) error {...},
	}
  //S'il existe une sous-sous-commande, définissez-la
  cmd.AddCommand(...)
  
  //Définir les options comme indicateurs
  cmd.Flags().StringVarp(...)
  
  //Inscrire le constructeur
  cc.baseBuilderCmd = b.newBuilderBasicCmd(cmd)
  
  return cc
}

Il sera complété en ajoutant les sous-commandes nécessaires au générateur de commandes. Vous pouvez avoir une bonne idée de la conception du générateur de commandes en consultant ce fichier (https://github.com/gohugoio/hugo/blob/master/commands/commands.go).

Serveur de traitement d'image avec Gin

Lors du POST d'une image avec http, j'ai créé une fonction pour traiter l'image et la sauvegarder dans le stockage d'objets (S3 cette fois). Le contenu de traitement est un mécanisme à lire à partir du fichier de paramètres. Il a été implémenté en supposant les fonctions qui peuvent être utilisées pour enregistrer des images de profil et créer des vignettes dans l'application.

La logique de Gin

J'ai lu Gin's GoDoc, qui est un framework Web créé par Go, et j'ai fait une image approximative. C'est un peu cassé, mais si vous le simplifiez, cela ressemble à ceci. Il semble que vous créez une logique qui renvoie une réponse HTTP à partir d'une requête HTTP en connectant les processus avec HandlerFunc (middleware).

↓ Image image.png

L'expression du traitement HTTP dans une chaîne middleware est très similaire à Express dans Node.js.

Téléchargement de fichiers vers S3

J'ai déraillé, mais revenons au processus de téléchargement de fichiers. Le flux de traitement est d'environ 3 étapes.

  1. Lisez l'image du client spécifié dans le corps de la requête HTTP et enregistrez-la dans le système de fichiers du serveur.
  2. Traitez le fichier lu avec la bibliothèque de création d'images.
  3. Téléchargez le fichier image traité dans S3 et renvoyez l'état de réussite.

J'ai fait référence à ce qui suit pour télécharger des fichiers vers Go. Veuillez consulter Amazon Web Services --Go SDK pour les paramètres détaillés.

Télécharger des fichiers vers S3 en langage Go (golang) \ | Developers.IO

En utilisant viper, il est possible d'accéder au fichier de configuration (config.json etc.) de paramètres détaillés tels que les paramètres de connexion de stockage d'objets et de sauvegarder le nom des images. est.

Sommaire

En enquêtant, j'ai trouvé un serveur de traitement d'image fabriqué par Go, qui est également introduit dans les réalisations de Gin.

C'est mieux conçu qu'un outil pour les débutants comme moi. J'ai décidé de l'utiliser sans hésitation lors de la mise en œuvre du service. Si vous trouvez une solution à ce que vous essayiez de faire, vous en apprendrez plus.

Pour le moment, je sentais que mon défi était de pouvoir maîtriser les packages standards de Go et le traitement parallèle. Les forfaits Go ont de bonnes perspectives et je ne suis pas trop fatigué donc je pense pouvoir m'entraîner pendant un moment.

Recommended Posts

J'ai fait une sorte d'outil de traitement d'image simple en langage Go.
J'ai écrit un outil CLI en langue Go pour afficher le flux de balises de Qiita dans CLI
J'ai fait un jeu de frappe simple avec tkinter de Python
J'ai fait une image ponctuelle de l'image d'Irasutoya. (partie 1)
J'ai fait une image ponctuelle de l'image d'Irasutoya. (partie 2)
Made Gomi, un outil de corbeille pour RM en langue Go
[Python] J'ai créé une visionneuse d'images avec une fonction de tri simple.
J'ai fait un programme de gestion de la paie en Python!
J'ai créé un outil d'estampage automatique du navigateur.
J'ai créé un outil de mot de passe en Python.
J'ai fait un simple blackjack avec Python
J'ai fait un programme pour vérifier la taille d'un fichier avec Python
J'ai fait une erreur en récupérant la hiérarchie avec MultiIndex of pandas
J'ai fait go language pour api et la configuration minimum de react pour le front
J'ai fait un outil pour estimer le temps d'exécution de cron (+ débuts de PyPI)
J'ai créé un outil utile pour Digital Ocean
J'ai créé un outil pour informer Slack des événements Connpass et en ai fait Terraform
[Python] [Traitement du langage naturel] J'ai essayé le Deep Learning ❷ fait de toutes pièces en japonais ①
J'ai créé une commande appdo pour exécuter des commandes dans le contexte de l'application
J'ai créé un outil de collecte de configuration de routeur Config Collecor
J'ai créé un outil pour compiler nativement Hy
J'ai fait un module en langage C qui filtre les images chargées par Python
J'ai créé un outil pour sauvegarder automatiquement les métadonnées de l'organisation Salesforce
J'ai créé un outil pour obtenir de nouveaux articles
J'ai fait un simple lecteur RSS ~ Edition C ~
J'ai créé un programme cryptographique César en Python.
Insoutenable manque d'attention dans le traitement du langage naturel
Après avoir effectué 100 traitements de langage en 2015, j'ai acquis beaucoup de compétences de base en Python Chapitre 1
Traitement d'image avec Python (j'ai essayé de le binariser en art mosaïque 0 et 1)
100 coups sur le traitement d'image !! (021-030) Je veux faire une pause ...
Liste des endroits sur lesquels je suis tombé lors du téléchargement d'images à partir de Django
Création de l'outil de gestion des utilisateurs Let's Chat
J'ai créé un outil de nettoyage pour Google Container Registry
J'ai créé une boîte de changement de seuil pour Pepper's Dialog
J'ai fait un script pour mettre un extrait dans README.md
Vérification des performances du prétraitement des données dans le traitement du langage naturel
Créer un serveur Web en langage Go (net / http) (1)
Afficher un histogramme des valeurs de luminosité de l'image en python
J'ai créé un outil de génération de données texte répétitif "rpttxt"
J'ai utilisé bugspots, un outil de prédiction de bogues dans mercurial
〇✕ J'ai fait un jeu
Caractéristiques du langage Go
J'ai créé un outil pour obtenir les liens de réponse d'OpenAI Gym en même temps
J'ai créé une fonction pour découper l'image de python openCV, alors veuillez l'utiliser.
J'ai créé un outil pour générer automatiquement un simple diagramme ER à partir de l'instruction CREATE TABLE
[Traitement du langage naturel] J'ai essayé de visualiser les remarques de chaque membre de la communauté Slack
Types de prétraitement dans le traitement du langage naturel et leur puissance
J'ai créé un lecteur de flux rapide en utilisant feedparser en Python
J'ai créé une application de livre simple avec python + Flask ~ Introduction ~
J'ai fait un jeu de combat Numer0n en Java (j'ai aussi fait de l'IA)
J'ai créé un outil pour créer un nuage de mots à partir de wikipedia