Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there an example of similarity measurement implemented by javacv #1598

Closed
4714407 opened this issue Feb 20, 2021 · 7 comments
Closed

Is there an example of similarity measurement implemented by javacv #1598

4714407 opened this issue Feb 20, 2021 · 7 comments
Labels

Comments

@4714407
Copy link

4714407 commented Feb 20, 2021

OpenCV official example are not implemented in Java.
Is there an implementation of javacv?

@saudet
Copy link
Member

saudet commented Feb 20, 2021

JavaCV comes with a Java mapping of the C++ API of OpenCV, so it should be pretty easy to translate an example written in C++, but if you encounter any issues, please let me know! I will be there to help.

@n-kai-cj
Copy link
Contributor

I wrote code for image similarity measurement with Java.
Please refer this.

    private static double getPSNR(Mat I1, Mat I2) {
        Mat s1 = new Mat();
        opencv_core.absdiff(I1, I2, s1);             // |I1 - I2|
        s1.convertTo(s1, opencv_core.CV_32F);        // cannot make a square on 8 bits
        s1 = s1.mul(s1).asMat();                     // |I1 - I2|^2

        Scalar s = opencv_core.sumElems(s1);         // sum elements per channel

        double sse = s.get(0) + s.get(1) + s.get(2); // sum channels

        if (sse <= 1e-10) {                          // for small values return zero
            return 0;
        } else {
            double mse = sse / (double) (I1.channels() * I1.total());
            double psnr = 10.0 * Math.log10((255 * 255) / mse);
            return psnr;
        }
    }

    private static Scalar getMSSIM(Mat i1, Mat i2) {
        double C1 = 6.5025, C2 = 58.5225;
        /***************************** INITS **********************************/
        int d = opencv_core.CV_32F;
        Mat I1 = new Mat();
        Mat I2 = new Mat();
        i1.convertTo(I1, d);                  // cannot calculate on one byte large values
        i2.convertTo(I2, d);
        Mat I2_2 = I2.mul(I2).asMat();        // I2^2
        Mat I1_2 = I1.mul(I1).asMat();        // I1^2
        Mat I1_I2 = I1.mul(I2).asMat();       // I1 * I2
        /*************************** END INITS **********************************/
        // PRELIMINARY COMPUTING
        Mat mu1 = new Mat();
        Mat mu2 = new Mat();
        opencv_imgproc.GaussianBlur(I1, mu1, new Size(11, 11), 1.5);
        opencv_imgproc.GaussianBlur(I2, mu2, new Size(11, 11), 1.5);
        Mat mu1_2 = mu1.mul(mu1).asMat();
        Mat mu2_2 = mu2.mul(mu2).asMat();
        Mat mu1_mu2 = mu1.mul(mu2).asMat();
        Mat sigma1_2 = new Mat();
        Mat sigma2_2 = new Mat();
        Mat sigma12 = new Mat();
        opencv_imgproc.GaussianBlur(I1_2, sigma1_2, new Size(11, 11), 1.5);
        sigma1_2 = opencv_core.subtract(sigma1_2, mu1_2).asMat();
        opencv_imgproc.GaussianBlur(I2_2, sigma2_2, new Size(11, 11), 1.5);
        sigma2_2 = opencv_core.subtract(sigma2_2, mu2_2).asMat();
        opencv_imgproc.GaussianBlur(I1_I2, sigma12, new Size(11, 11), 1.5);
        sigma12 = opencv_core.subtract(sigma12, mu1_mu2).asMat();
        Mat t1, t2, t3;
        t1 = opencv_core.add(opencv_core.multiply(2, mu1_mu2), Scalar.all(C1)).asMat();
        t2 = opencv_core.add(opencv_core.multiply(2, sigma12), Scalar.all(C2)).asMat();
        t3 = t1.mul(t2).asMat();                     // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))
        t1 = opencv_core.add(opencv_core.add(mu1_2, mu2_2), Scalar.all(C1)).asMat();
        t2 = opencv_core.add(opencv_core.add(sigma1_2, sigma2_2), Scalar.all(C2)).asMat();
        t1 = t1.mul(t2).asMat();                     // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))
        Mat ssim_map = new Mat();
        opencv_core.divide(t3, t1, ssim_map);        // ssim_map =  t3./t1;
        Scalar mssim = opencv_core.mean(ssim_map);   // mssim = average of ssim map
        return mssim;
    }

    public static void main(String[] args) {
        Mat img1 = opencv_imgcodecs.imread("img.png");
        Mat img2 = img1.clone();
        opencv_imgproc.GaussianBlur(img2, img2, new Size(15, 15), 10);
        double psnr = getPSNR(img1, img2);
        Scalar mssim = getMSSIM(img1, img2);
        System.out.println("PSNR: " + psnr);
        System.out.printf("SSIM: %f, %f, %f\n", mssim.get(0), mssim.get(1), mssim.get(2));
    }

example run:

PSNR: 24.436830178936226
SSIM: 0.652272, 0.615158, 0.652056

@4714407
Copy link
Author

4714407 commented Apr 10, 2021

Thank you very much for the code!

@4714407 4714407 closed this as completed Apr 10, 2021
@saudet
Copy link
Member

saudet commented Apr 10, 2021

@n-kai-cj Thanks! Could you send a pull request to include that as a sample in
https://github.com/bytedeco/javacv/tree/master/samples ?

@n-kai-cj
Copy link
Contributor

sent pull request #1622

@GuaiYiHu
Copy link

asMat out of memory

@saudet
Copy link
Member

saudet commented Sep 19, 2022

@GuaiYiHu Try to call close() on all Mat objects you create that way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants