OpenCV, вариант лапласиана (Java)

Я пытаюсь найти вариацию для лапласиана на основе изображения с целью получения числового значения на основе размытости изображения.

Это полезный пост http://www.pyimagesearch.com/2015/09/07/blur-detection-with-opencv/

cv2.Laplacian(image, cv2.CV_64F).var()

Я пытался реализовать то же самое без везения. Моя отправная точка — это byte[], представляющий изображение (img):

Mat mat = new Mat(img.getImageHeight(), img.getImageWidth(), CvType.CV_8UC3);
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY);
mat.put(0, 0, putData.getFileContents());
Imgproc.Laplacian(mat,mat, CvType.CV_64F);

Любая помощь будет оценена по достоинству.

По сути, я начинаю с изображения и хочу получить значение, представляющее размытость изображения с помощью лапласиана.


person Scott    schedule 04.04.2016    source источник


Ответы (2)


Преобразование Лапласа можно заменить ядром, примененным с помощью метода filter2D. Я запускал тот же пример Python в такой Java-программе:

    Mat destination = new Mat();
    Mat matGray=new Mat();  
    Mat kernel = new Mat(3,3, CvType.CV_32F){
       {
          put(0,0,0);
          put(0,1,-1);
          put(0,2,0);

          put(1,0-1);
          put(1,1,4);
          put(1,2,-1);

          put(2,0,0);
          put(2,1,-1);
          put(2,2,0);
       }
    };        
    Imgproc.cvtColor(image, matGray, Imgproc.COLOR_BGR2GRAY);          
    Imgproc.filter2D(matGray, destination, -1, kernel); 
    MatOfDouble median = new MatOfDouble();
    MatOfDouble std= new MatOfDouble();        
    Core.meanStdDev(destination, median , std);

    Math.pow(std.get(0,0)[0],2);

Надеюсь, это поможет вашему кодированию.

Примечание. Значения, которые я получаю из программы Python и Java, различаются, и я до сих пор не понял, почему. В любом случае код Java работает хорошо.

Выяснил, почему значения не совпадают. Использование метода Imgproc.Laplacian вместо Imgproc.filter2D дает точно такие же значения в python и java.

Новый код становится:

Mat destination = new Mat();
Mat matGray=new Mat();  

Imgproc.cvtColor(image, matGray, Imgproc.COLOR_BGR2GRAY);          
Imgproc.Laplacian(matGray, destination, 3); 
MatOfDouble median = new MatOfDouble();
MatOfDouble std= new MatOfDouble();        
Core.meanStdDev(destination, median , std);

Math.pow(std.get(0,0)[0],2);

Гораздо проще и с теми же результатами, что и python.

person Pedro Nogueira    schedule 20.12.2016
comment
Я также использовал этот алгоритм, чтобы найти лучшее значение фокуса в наборе изображений, снятых с разными фокусными расстояниями. Однако я только что оценил 2 изображения, результаты которых неверны. Мои входные изображения имеют оттенки серого, поэтому я создаю изображение следующим образом: Mat image = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.CV_LOAD_IMAGE_UNCHANGED) Я не думаю, что смогу загрузить изображения в этот пост, но если кому-то интересно на них посмотреть, я могу отправить их вам. - person Eric Hansen; 31.01.2020

Я не нашел прямой функции для вычисления дисперсии изображения в OpenCV. Но я нашел кое-что для расчета среднего стандартного отклонения. А из математики дисперсия — это просто квадрат среднего стандартного отклонения.

Вот как я вычисляю среднее стандартное отклонение изображения

Mat im = Imgcodecs.imread("relative/path/to/file");
Imgproc.cvtColor(im, im, Imgproc.COLOR_BGR2GRAY);
MatOfDouble mu = new MatOfDouble(); // mean
MatOfDouble sigma = new MatOfDouble(); // standard deviation
Core.meanStdDev(d, mu, sigma);
double variance = Math.pow(mu.get(0,0)[0], 2);

Я запустил это на 37 JPG-файлах, которые я преобразовал из RAW (каждый около 8 МБ), и это работало, хотя и медленно. Я попытался сделать это для своих 340 фотографий, и мой ноутбук выключился. Должны быть способы оптимизировать это.

person iGbanam    schedule 01.12.2016
comment
Прежде всего, спасибо за ваш пост! Пожалуйста, дайте мне знать, откуда берется переменная «d»? Каково значение д? Это то же самое, что и я? - person ; 20.01.2018