This article describes the example code of Java to obtain the main color in a color image. Share it for your reference, as follows:
1: Basic ideas
For a color image in RGB color space, we want to obtain several main colors of the image through the program in many times. However, for general images, pixel mixing is achieved at the color junction. Therefore, directly scanning the pixel values of the image may result in as many as hundreds of different color values. In fact, the image may only have 3 to 4 main colors. How to remove those mixed colors and accurately extract the main colors of these 3 to 4. According to the characteristics of the general image, the image will not be Mixing different color values at the boundary of the same color can be regarded as one of the edge characteristics of the image. Therefore, the extract of these mixed pixels can be achieved according to a simple edge gradient algorithm to obtain the output pixel value array, and then scanning each pixel value, looking for the pixels around the specified radius parameter R, and finding zero, and the value of the pixel point closest to the center pixel is used as the pixel value of the center pixel. After the scan is completed, the pixel array can be output, and then linearly scanning the array can be obtained to obtain the main color RGB value of the picture.
Two: Implementation steps
1. Enter an image array to grayscale the color image;
2. For the grayscale image, calculate the image gradient, and use the sobol operator here;
3. For each non-zero pixel point, scan within the range of radius R, and find the nearest original pixel value of zero;
4. Simply scan the obtained array to get the main color.
The parameter R is to find the most suitable value according to different application scenarios. Theoretically, the larger the image, the larger the value of R should be, otherwise the algorithm will be inaccurate.
Three: Original picture and operation effect
Original image
After the algorithm is run, four main colors are extracted
Four: Algorithm implementation source code
public static BufferedImage removeBlendPixels(BufferedImage image, int raidus) { int width = image.getWidth(); int height = image.getHeight(); int[] pixels = new int[width * height]; getRGB(image, 0, 0, width, height, pixels); // Create processing resultBufferedImage resultImg = createCompatibleDestImage(image, null); setRGB(resultImg, 0, 0, width, height, pixels); // Create processing resultBufferedImage resultImg = createCompatibleDestImage(image, null); setRGB(resultImg, 0, 0, width, height, pixels); // Grayscale and gradient byte[] grayData = getGrayData(pixels, width, height); byte[] binaryData = getGrident(grayData, width, height); 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 = -raidus; subrow <= raidus; subrow++) { nr = row + subrow; if (nr < 0 || nr >= height) { continue; } for (int subcol = -raidus; subcol <= raidus; subcol++) { nc = col + subcol; if (nc < 0 || nc >= width) { continue; } index2 = nr * width + nc; int value = (binaryData[index2] & 0xff); if (value == 0) { int distance = distanceColor(image.getRGB(nc, nr), image.getRGB(col, row)); if (distance < mindis) { mindis = distance; minrow = nr; mincol = nc; } } } } resultImg.setRGB(col, row, image.getRGB(mincol, minrow)); } } } return resultImg; } public static int distanceColor(int rgb, int rgb2) { // Color one int r1 = (rgb >> 16) & 0xff; int g1 = (rgb >> 8) & 0xff; int b1 = rgb & 0xff; // Color two 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); return sum; } public static byte[] getGrayData(int[] inPixels, int width, int height) { // Image grayscale byte[] outPixels = new byte[width * height]; int index = 0; for (int row = 0; row < height; row++) { int tr = 0, tg = 0, tb = 0; for (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 gray = (int) (0.299 * tr + 0.587 * tg + 0.114 * tb); outPixels[index] = (byte) (gray & 0xff); } } return outPixels; } public static byte[] getGrident(byte[] inPixels, int width, int height) { byte[] outPixels = new byte[width * height]; int index = 0; for (int row = 0; row < height; row++) { int tr = 0; for (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); continue; } 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 >= width) { 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 * width + col; int g = (int) Math.sqrt(xg * xg + yg * yg); outPixels[index] = (byte) (clamp(g) & 0xff); } } return outPixels; } The constant values that need to be defined are as follows:
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; Gradient acquisition uses sobol operator. The code for scanning the BufferedImage object after processing to obtain the main color is as follows:
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); } } } // now scan pixel value // return result System.out.println("number of color = " + colorIndexMap.size()); return colorIndexMap.keySet().toArray(new Integer[0]); The test code is as follows:
public static void main(String[] args) { File file = new File("D://gloomyfish//bigmonkey.png"); File resultFile = new File("D://gloomyfish//result.png"); try { BufferedImage image = ImageIO.read(file); BufferedImage result = removeBlendPixels(image, BLOCK_PIXEL_RADIUS); ImageIO.write(result, "png", resultFile); Integer[] colors = extractColors(result); System.out.println("total colors : " + colors.length); } catch (IOException e) { e.printStackTrace(); } }Note: The main key is to input the correct size of the image to be processed. This radius size is related to the actual size of the image, and the algorithm can be optimized one step further into a version that does not depend on the radius parameter, until you find a pixel equal to zero.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.