package com.isaac.enhance; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.Scalar; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.CLAHE; import org.opencv.imgproc.Imgproc; import com.isaac.utils.ColorBalance; import com.isaac.utils.ImShow; public class EnhanceFunc { static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } public static void main(String[] args) { String imgPath = "images/5.jpg"; Mat image = Imgcodecs.imread(imgPath, Imgcodecs.CV_LOAD_IMAGE_COLOR); new ImShow("original").showImage(image); // color balance Mat img1 = ColorBalance.SimplestColorBalance(image, 5); img1.convertTo(img1, CvType.CV_8UC1); // Perform sRGB to CIE Lab color space conversion Mat LabIm1 = new Mat(); Imgproc.cvtColor(img1, LabIm1, Imgproc.COLOR_BGR2Lab); Mat L1 = new Mat(); Core.extractChannel(LabIm1, L1, 0); // apply CLAHE Mat[] result = applyCLAHE(LabIm1, L1); Mat img2 = result[0]; Mat L2 = result[1]; // calculate normalized weight Mat w1 = calWeight(img1, L1); Mat w2 = calWeight(img2, L2); Mat sumW = new Mat(); Core.add(w1, w2, sumW); Core.divide(w1, sumW, w1); Core.divide(w2, sumW, w2); // construct the gaussian pyramid for weight int level = 5; Mat[] weight1 = Pyramid.GaussianPyramid(w1, level); Mat[] weight2 = Pyramid.GaussianPyramid(w2, level); // construct the laplacian pyramid for input image channel img1.convertTo(img1, CvType.CV_32F); img2.convertTo(img2, CvType.CV_32F); List<Mat> bgr = new ArrayList<Mat>(); Core.split(img1, bgr); Mat[] bCnl1 = Pyramid.LaplacianPyramid(bgr.get(0), level); Mat[] gCnl1 = Pyramid.LaplacianPyramid(bgr.get(1), level); Mat[] rCnl1 = Pyramid.LaplacianPyramid(bgr.get(2), level); bgr.clear(); Core.split(img2, bgr); Mat[] bCnl2 = Pyramid.LaplacianPyramid(bgr.get(0), level); Mat[] gCnl2 = Pyramid.LaplacianPyramid(bgr.get(1), level); Mat[] rCnl2 = Pyramid.LaplacianPyramid(bgr.get(2), level); // fusion process Mat[] bCnl = new Mat[level]; Mat[] gCnl = new Mat[level]; Mat[] rCnl = new Mat[level]; for (int i = 0; i < level; i++) { Mat cn = new Mat(); Core.add(bCnl1[i].mul(weight1[i]), bCnl2[i].mul(weight2[i]), cn); bCnl[i] = cn.clone(); Core.add(gCnl1[i].mul(weight1[i]), gCnl2[i].mul(weight2[i]), cn); gCnl[i] = cn.clone(); Core.add(rCnl1[i].mul(weight1[i]), rCnl2[i].mul(weight2[i]), cn); rCnl[i] = cn.clone(); } // reconstruct & output Mat bChannel = Pyramid.PyramidReconstruct(bCnl); Mat gChannel = Pyramid.PyramidReconstruct(gCnl); Mat rChannel = Pyramid.PyramidReconstruct(rCnl); Mat fusion = new Mat(); Core.merge(new ArrayList<Mat>(Arrays.asList(bChannel, gChannel, rChannel)), fusion); fusion.convertTo(fusion, CvType.CV_8UC1); new ImShow("fusion").showImage(fusion); } private static Mat[] applyCLAHE(Mat img, Mat L) { Mat[] result = new Mat[2]; CLAHE clahe = Imgproc.createCLAHE(); clahe.setClipLimit(2.0); Mat L2 = new Mat(); clahe.apply(L, L2); Mat LabIm2 = new Mat(); List<Mat> lab = new ArrayList<Mat>(); Core.split(img, lab); Core.merge(new ArrayList<Mat>(Arrays.asList(L2, lab.get(1), lab.get(2))), LabIm2); Mat img2 = new Mat(); Imgproc.cvtColor(LabIm2, img2, Imgproc.COLOR_Lab2BGR); result[0] = img2; result[1] = L2; return result; } private static Mat calWeight(Mat img, Mat L) { Core.divide(L, new Scalar(255.0), L); L.convertTo(L, CvType.CV_32F); // calculate laplacian contrast weight Mat WL = WeightCalculate.LaplacianContrast(L); WL.convertTo(WL, L.type()); // calculate Local contrast weight Mat WC = WeightCalculate.LocalContrast(L); WC.convertTo(WC, L.type()); // calculate the saliency weight Mat WS = WeightCalculate.Saliency(img); WS.convertTo(WS, L.type()); // calculate the exposedness weight Mat WE = WeightCalculate.Exposedness(L); WE.convertTo(WE, L.type()); // sum Mat weight = WL.clone(); Core.add(weight, WC, weight); Core.add(weight, WS, weight); Core.add(weight, WE, weight); return weight; } }