OpenCV彩色图像直方图匹配

时间:2016-12-15 14:29:35

标签: android image-processing histogram opencv3.1

我正在尝试编写一个Android应用程序,它使用OpenCV3.1执行彩色图像的直方图匹配。我在C ++中找到this code example,并将其转换为java。 我试图分别匹配每个RGB chanel,但它没有给我想要的结果。所以现在我将图像转换为YUV颜色空间,然后匹配Y香奈儿。我希望实现的是brightnes匹配,所以如果光源更亮,那么目标我会变得更暗。

到目前为止,似乎最终(输出)图像的Y直方图有点接近目标图像的Y直方图,但实际输出看起来不像目标。

以下是相关代码:

private Mat calculateLUT(Mat in_cdf_mat, Mat dst_cdf_mat) {
    int last = 0;
    double epsilon = Double.parseDouble(epsilonTextView.getText().toString());// epsilon set to 0.01
    Mat M = new Mat(256, 1,CvType.CV_8UC1);
    for(int j=0; j<in_cdf_mat.rows(); j++) {
        double F1j = in_cdf_mat.get(j,0)[0];
        for(int k = last; k < dst_cdf_mat.rows(); k++) {
            double F2k = dst_cdf_mat.get(k,0)[0];
            if(Math.abs(F2k - F1j) < epsilon || F2k > F1j) {
                double[] data = {k} ;
                M.put(j, 0, data);
                last = k;
                break;
            }
        }
    }
    return M;
}

private void calculateCDF (Mat channel, Mat cdf)
{
    //  channel holds the histogram. The indices represents the pixel color
    // and the value is the amount of pixels of that color in the image
    for (int i = 1; i < 256; i++) {
        double[] data = new double[1];
        data[0] = cdf.get(i-1,0)[0] + channel.get(i,0)[0];
        cdf.put(i, 0, data);
    }
}

private void calcHistogram(String imgPath, Mat y_hist, Mat y_cdf) {
    Mat image;
    Mat ycrcb = new Mat();
    image = Imgcodecs.imread(imgPath);

    Imgproc.cvtColor(image, ycrcb, Imgproc.COLOR_RGB2YCrCb);
    image.release();

    List<Mat> ycrcbChannels= new ArrayList<>();
    Core.split(ycrcb,ycrcbChannels);

    List<Mat> yList = new ArrayList<>();
    yList.add(ycrcbChannels.get(0));

    MatOfInt histSize = new MatOfInt(256);
    MatOfFloat histRange = new MatOfFloat(0f, 256f);

    Imgproc.calcHist(yList, new MatOfInt(0), new Mat(), y_hist, histSize, histRange, false);
    Core.normalize(y_hist, y_hist, 3, 255, Core.NORM_MINMAX);

    calculateCDF(y_hist, y_cdf);
    Core.normalize(y_cdf, y_cdf, 3, 255, Core.NORM_MINMAX);
}

private void transformLight(Mat inputImage, Mat outputImage, Mat ylut) {

    Mat imageYCrCb = new Mat();
    Imgproc.cvtColor(inputImage, imageYCrCb, Imgproc.COLOR_RGB2YCrCb);

    Mat y_chanel = new Mat();
    Core.extractChannel(imageYCrCb, y_chanel, 0);
    Mat cr_chanel = new Mat();
    Core.extractChannel(imageYCrCb, cr_chanel, 1);
    Mat cb_chanel = new Mat();
    Core.extractChannel(imageYCrCb, cb_chanel, 2);

    Core.LUT(y_chanel, ylut,y_chanel);

    ArrayList<Mat> ycrcbDest = new ArrayList<>();
    ycrcbDest.add(y_chanel);
    ycrcbDest.add(cr_chanel);
    ycrcbDest.add(cb_chanel);

    Core.merge(ycrcbDest,outputImage);

    Imgproc.cvtColor(outputImage, outputImage, Imgproc.COLOR_YCrCb2RGB);
}

private static void drawLine (Mat mat, int i,  long bin_w, int hist_h, Mat histImage, Scalar color) {
    // bin_w set to 1
    Point p0 = new Point(bin_w * (i - 1), hist_h - Math.round(mat.get(i-1,0)[0]) );
    Point p1 = new Point(bin_w * (i), hist_h - Math.round(mat.get(i,0)[0]) );
    Imgproc.line(histImage, p0, p1, color, 5, 8, 0);
}

private void drawHistogram(Mat histImage, Mat graph, Scalar color) {
    for (int i = 1; i < 256; i++) {
        drawLine(graph, i, bin_w, histImage.rows(), histImage, color);
    }
}


private void histNCDFtoFile(String filename, Mat hist, Mat cdf, Scalar histColor, Scalar cdfColor) {
    Mat histImage = new Mat(256, 256, CvType.CV_8UC3);
    drawHistogram(histImage, hist, histColor);
    drawHistogram(histImage, cdf, cdfColor);
    saveImage(filename, histImage);
}

private Mat matchHistograms(String input, String traget) {
    Mat input_y_hist = new Mat();
    Mat target_y_hist = new Mat();

    calcHistogram(input, input_y_hist, input_y_cdf_mat);
    histNCDFtoFile("inputHistNCDF.jpg", input_y_hist, input_y_cdf_mat, inputHistColor, inputCDFColor);

    calcHistogram(traget, target_y_hist, target_y_cdf_mat);
    histNCDFtoFile("targetHistNCDF.jpg", target_y_hist, target_y_cdf_mat, targetHistColor, targetCDFColor);

    Mat ylut = calculateLUT(input_y_cdf_mat, target_y_cdf_mat);

    Mat image;
    Mat dst = new Mat(); // this Matrix will hold the transformed image
    image = Imgcodecs.imread(input);
    transformLight(image, dst, ylut);
    return dst;
}

这是pixabay想要转换的一个例子: input image 这是我用作目标的图像: enter image description here 这就是结果: enter image description here

结果和目标的CDF在这里:

enter image description here

浅绿色是目标CDF,浅蓝色是结果CDF

0 个答案:

没有答案