Cet article décrit l'exemple de code de Java pour obtenir la couleur principale d'une image couleur. Partagez-le pour votre référence, comme suit:
1: idées de base
Pour une image couleur dans l'espace colorimétrique RVB, nous voulons obtenir plusieurs couleurs principales de l'image à travers le programme à plusieurs reprises. Cependant, pour les images générales, le mélange de pixels est obtenu à la jonction des couleurs. Par conséquent, le balayage directement les valeurs de pixels de l'image peut entraîner jusqu'à des centaines de valeurs de couleur différentes. En fait, l'image ne peut avoir que 3 à 4 couleurs principales. Comment éliminer ces couleurs mixtes et extraire avec précision les couleurs principales de ces 3 à 4. Selon les caractéristiques de l'image générale, l'image ne mélangera pas différentes valeurs de couleur à la limite de la même couleur peut être considérée comme l'une des caractéristiques de bord de l'image. Par conséquent, l'extrait de ces pixels mixtes peut être réalisé en fonction d'un algorithme de gradient de bord simple pour obtenir le tableau de valeur de pixel de sortie, puis à balayer chaque valeur de pixel, à la recherche des pixels autour du paramètre RADIUS spécifié R, et à la recherche de zéro, et la valeur du point de pixel le plus proche du pixel central est utilisée comme valeur pixel du pixel central. Une fois le scan terminé, le réseau de pixels peut être sorti, puis le balayage linéaire du tableau peut être obtenu pour obtenir la valeur RVB de couleur principale de l'image.
Deux: étapes de mise en œuvre
1. Entrez un tableau d'image pour en niveaux de gris l'image couleur;
2. Pour l'image en niveaux de gris, calculez le gradient d'image et utilisez l'opérateur SOBOL ici;
3. Pour chaque point de pixel non nul, scannez dans la plage de rayon R et trouvez la valeur de pixel d'origine la plus proche de zéro;
4. SCAYEZ simplement le tableau obtenu pour obtenir la couleur principale.
Le paramètre R est de trouver la valeur la plus appropriée en fonction des différents scénarios d'application. Théoriquement, plus l'image est grande, plus la valeur de R devrait être grande, sinon l'algorithme sera inexact.
Trois: Effet d'image et d'opération d'origine
Image originale
Une fois l'algorithme exécuté, quatre couleurs principales sont extraites
Quatre: code source d'implémentation de l'algorithme
Public Static BufferedImage RemoveLndPixels (BufferedImage Image, int raidus) {int width = image.getWidth (); int height = image.getheight (); int [] pixels = new int [largeur * hauteur]; getRGB (image, 0, 0, largeur, hauteur, pixels); // Créer un traitement ResultimeBufferedImage resultimg = createCompatibleStimage (image, null); setRGB (résultat, 0, 0, largeur, hauteur, pixels); // Créer un traitement ResultimeBufferedImage resultimg = createCompatibleStimage (image, null); setRGB (résultat, 0, 0, largeur, hauteur, pixels); // octet de gris et gradient [] graydata = getGraydata (pixels, largeur, hauteur); octet [] binaryData = getGrident (graydata, largeur, hauteur); int index = 0; for (int row = 1; row <height - 1; row ++) {for (int col = 1; col <width - 1; col ++) {index = row * width + col; int pixel = (binaryData [index] & 0xff); if (pixel> 0) {// Radius Scan Operation int MindiS = Integer.max_value; int minRow = -1; int mincol = -1; int nr = 0; int nc = 0; int index2 = 0; for (int subrow = -radeus; subrow <= raidus; subrow ++) {nr = row + subrow; if (nr <0 || nr> = height) {continue; } pour (int subcol = -raraidUS; subcol <= raidus; subcol ++) {nc = col + subcol; if (nc <0 || nc> = largeur) {continue; } index2 = nr * largeur + nc; int value = (binaryData [index2] & 0xff); if (value == 0) {int Distance = DistanceColor (image.getrgb (nc, nr), image.getrgb (col, row)); if (Distance <MINIS) {MINIS = Distance; minrow = nr; mincol = nc; }}}} résultattimg.setrgb (col, row, image.getrgb (Mincol, Minrow)); }}} return resultImg; } public static int DistanceColor (int rgb, int rgb2) {// colore un int r1 = (rgb >> 16) & 0xff; int g1 = (rgb >> 8) & 0xff; int b1 = rgb & 0xff; // Color deux int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; // Distance int rr = r1 - r2; int gg = g1 - g2; int bb = b1 - b2; int sum = (int) math.sqrt (rr * rr + gg * gg + bb * bb); somme de retour; } octet statique publique [] getGrayData (int [] inpixels, int largeur, int hauteur) {// Image Graycale octet [] uptixels = nouveau octet [largeur * hauteur]; int index = 0; pour (int row = 0; row <height; row ++) {int tr = 0, tg = 0, tb = 0; pour (int col = 0; col <width; col ++) {index = row * width + col; tr = (inpixels [index] >> 16) & 0xff; tg = (inpixels [index] >> 8) & 0xff; tb = inpixels [index] & 0xff; int gris = (int) (0,299 * tr + 0,587 * tg + 0,114 * tb); OutPixels [index] = (byte) (gris & 0xff); }} return OutPixels; } byte statique public [] getGrident (byte [] inpixels, int largeur, int hauteur) {octet [] upxels = nouveau octet [largeur * hauteur]; int index = 0; pour (int row = 0; row <hight; row ++) {int tr = 0; pour (int col = 0; col <width; col ++) {if (row == 0 || col == 0 || (row == height - 1) || (col == width - 1)) {index = row * width + col; OutPixels [index] = (byte) (0x00); continuer; } int xg = 0, yg = 0; for (int sr = -1; sr <= 1; sr ++) {for (int sc = -1; sc <= 1; sc ++) {int nrow = row + sr; int ncol = col + sc; if (nrow <0 || nrow> = height) {nrow = 0; } if (ncol <0 || ncol> = largeur) {ncol = 0; } index = nrow * width + ncol; tr = (inpixels [index] & 0xff); xg + = x_sobel [sr + 1] [sc + 1] * tr; yg + = y_sobel [sr + 1] [sc + 1] * tr; }} index = row * largeur + col; int g = (int) math.sqrt (xg * xg + yg * yg); OutPixels [index] = (byte) (clamp (g) & 0xff); }} return OutPixels; } Les valeurs constantes qui doivent être définies sont comme suit:
public static final int [] [] x_sobel = new int [] [] {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}}; public static final int [] [] y_sobel = new int [] [] {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}}; public static final int block_pixel_radius = 5; L'acquisition de gradient utilise l'opérateur SOBOL. Le code de numérisation de l'objet BufferedImage après le traitement pour obtenir la couleur principale est le suivant:
int width = result.getWidth (); int height = result.getheight (); Map <Integer, Integer> colorIndexMap = new HashMap <Integer, Integer> (); for (int row = 0; row <height; row ++) {for (int col = 0; col <width; col ++) {int pixelvalue = result.getrgb (col, row); if (! ColorIndexmap.ContainsKey (pixelValue)) {colorIndexmap.put (pixelValue, pixelValue); }}} // Scannez maintenant la valeur de pixels // return result system.out.println ("nombre de color =" + colorIndexmap.size ()); return colorIndexmap.KeySet (). ToArray (nouvel entier [0]); Le code de test est le suivant:
public static void main (String [] args) {file file = new File ("d: //gloomyfish//bigmonkey.png"); File resultFile = nouveau fichier ("d: //gloomyfish//result.png"); try {bufferedImage image = imageo.read (file); BufferedImage Result = reousblendPixels (image, block_pixel_radius); ImageIo.Write (résultat, "png", résultat); Entier [] couleurs = extractColors (résultat); System.out.println ("Total Colors:" + Colors.Length); } catch (ioException e) {e.printStackTrace (); }}Remarque: La clé principale consiste à saisir la taille correcte de l'image à traiter. Cette taille de rayon est liée à la taille réelle de l'image, et l'algorithme peut être optimisé un pas plus loin dans une version qui ne dépend pas du paramètre de rayon, jusqu'à ce que vous trouviez un pixel égal à zéro.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.