OpenCV, вариация лапласиана (Java)
Я пытаюсь найти вариацию для лапласиана на основе изображения с целью получения числового значения, основанного на размытости изображения.
Это полезный пост http://www.pyimagesearch.com/2015/09/07/blur-detection-with-opencv/
cv2.Laplacian(image, cv2.CV_64F).var()
Я пытался реализовать то же самое без удачи. Моя отправная точка - байт [], представляющий изображение (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);
Любая помощь будет оценена.
По сути, я начинаю с изображения и хочу получить значение, представляющее размытость изображения, с помощью лапласиана.
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.
Я не нашел никакой прямой функции для вычисления дисперсии изображения в 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 фотографий, и мой ноутбук выключился. Должны быть способы оптимизировать это.