package com.isaac.utils; import java.util.ArrayList; import java.util.List; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; public class ColorBalance { /** * Simplest Color Balance. Performs color balancing via histogram * normalization. * * @param img * input color or gray scale image * @param percent * controls the percentage of pixels to clip to white and black. * (normally, choose 1~10) * @return Balanced image in CvType.CV_32F */ public static Mat SimplestColorBalance(Mat img, int percent) { if (percent <= 0) percent = 5; img.convertTo(img, CvType.CV_32F); List<Mat> channels = new ArrayList<Mat>(); int rows = img.rows(); // number of rows of image int cols = img.cols(); // number of columns of image int chnls = img.channels(); // number of channels of image double halfPercent = percent / 200.0; if (chnls == 3) { Core.split(img, channels); } else { channels.add(img); } List<Mat> results = new ArrayList<Mat>(); for (int i = 0; i < chnls; i++) { // find the low and high precentile values (based on the input percentile) Mat flat = new Mat(); channels.get(i).reshape(1, 1).copyTo(flat); Core.sort(flat, flat, Core.SORT_ASCENDING); double lowVal = flat.get(0, (int) Math.floor(flat.cols() * halfPercent))[0]; double topVal = flat.get(0, (int) Math.ceil(flat.cols() * (1.0 - halfPercent)))[0]; // saturate below the low percentile and above the high percentile Mat channel = channels.get(i); for (int m = 0; m < rows; m++) { for (int n = 0; n < cols; n++) { if (channel.get(m, n)[0] < lowVal) channel.put(m, n, lowVal); if (channel.get(m, n)[0] > topVal) channel.put(m, n, topVal); } } Core.normalize(channel, channel, 0, 255, Core.NORM_MINMAX); channel.convertTo(channel, CvType.CV_32F); results.add(channel); } Mat outval = new Mat(); Core.merge(results, outval); return outval; } }