[英]Detecting if image is blurred using OpenCV
使用this和this作為參考,我將以下 2 個函數放在一起以嘗試檢測圖像是否模糊:
public static boolean checkIfImageIsBlurred(BitmapRegionDecoder bitmapRegionDecoder) {
if (bitmapRegionDecoder == null) {
Timber.e("Expected bitmapRegionDecoder was null");
return true;
}
int loadImageHeight = bitmapRegionDecoder.getHeight();
int loadImageWidth = bitmapRegionDecoder.getWidth();
int checkImageTopPosition = 0;
int checkImageBottomPosition = loadImageHeight / 10;
int checkImageLeftPosition = 0;
int checkImageRightPosition = loadImageWidth / 10;
int totalDividedRectangles = 0;
int numberOfBlurredRectangles = 0;
while ((checkImageRightPosition <= loadImageWidth) && (checkImageLeftPosition < checkImageRightPosition)) {
while ((checkImageBottomPosition <= loadImageHeight) && (checkImageTopPosition < checkImageBottomPosition)) {
Timber.d("left: " + checkImageLeftPosition + " right: " + checkImageRightPosition + " top: " + checkImageTopPosition + " bottom: " + checkImageBottomPosition);
Rect rect = new Rect(checkImageLeftPosition,checkImageTopPosition,checkImageRightPosition,checkImageBottomPosition);
totalDividedRectangles++;
Bitmap processBitmap = bitmapRegionDecoder.decodeRegion(rect,null);
if (checkIfImageIsBlurred(processBitmap)) {
numberOfBlurredRectangles++;
}
checkImageTopPosition = checkImageBottomPosition;
checkImageBottomPosition += (checkImageBottomPosition < (loadImageHeight - checkImageBottomPosition)) ? checkImageBottomPosition: (loadImageHeight - checkImageBottomPosition);
}
checkImageTopPosition = 0; //reset to start
checkImageBottomPosition = loadImageHeight / 10; //reset to start
checkImageLeftPosition = checkImageRightPosition;
checkImageRightPosition += (checkImageRightPosition < (loadImageWidth - checkImageRightPosition)) ? checkImageRightPosition : (loadImageWidth - checkImageRightPosition);
}
Timber.d("blurred rectangles count = " + numberOfBlurredRectangles + ", total rectangles count = " + totalDividedRectangles);
return numberOfBlurredRectangles > totalDividedRectangles * 0.50;
}
public static boolean checkIfImageIsBlurred(Bitmap bitmap) {
if(bitmap == null) {
Timber.e("Expected bitmap was null");
return false;
}
Mat imageBitmapMat = new Mat(bitmap.getWidth(),bitmap.getHeight(),CvType.CV_8UC1);
Utils.bitmapToMat(bitmap,imageBitmapMat);
Mat grayscaleBitmapMat = new Mat();
Imgproc.cvtColor(imageBitmapMat,grayscaleBitmapMat,Imgproc.COLOR_RGB2GRAY);
Mat postLaplacianMat = new Mat();
Imgproc.Laplacian(grayscaleBitmapMat,postLaplacianMat,3);
MatOfDouble mean = new MatOfDouble();
MatOfDouble standardDeviation = new MatOfDouble();
Core.meanStdDev(postLaplacianMat,mean,standardDeviation);
double result = Math.pow(standardDeviation.get(0,0)[0],2);
Timber.d("blurry result = " + result);
return result < 100;
}
由於從相機拍攝的圖像太大,我使用 BitmapRegionDecoder 獲取其中的一部分,然后檢查整個圖像的那部分是否模糊。 如果拉普拉斯算子的變化小於定義的閾值,則圖像被聲明為模糊,在本例中為 100(該值取自所附的第一篇文章)。 如果發現超過 50% 的圖像“部分”是模糊的,則整個圖像被認為是模糊的。
經過測試,我發現結果是不確定的。 我測試的大部分圖像都被聲明為模糊。 我什至嘗試改變所使用的拉普拉斯閾值的變化,但沒有找到一個提供始終正確結果的值,這讓我認為我做錯了什么。
您可以使用以下方法來檢測圖像是否模糊。
private synchronized boolean isBlurredImage(Bitmap image) {
try {
if (image != null) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inDither = true;
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
int l = CvType.CV_8UC1;
Mat matImage = new Mat();
Utils.bitmapToMat(image, matImage);
Mat matImageGrey = new Mat();
Imgproc.cvtColor(matImage, matImageGrey, Imgproc.COLOR_BGR2GRAY);
Mat dst2 = new Mat();
Utils.bitmapToMat(image, dst2);
Mat laplacianImage = new Mat();
dst2.convertTo(laplacianImage, l);
Imgproc.Laplacian(matImageGrey, laplacianImage, CvType.CV_8U);
Mat laplacianImage8bit = new Mat();
laplacianImage.convertTo(laplacianImage8bit, l);
System.gc();
Bitmap bmp = Bitmap.createBitmap(laplacianImage8bit.cols(),
laplacianImage8bit.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(laplacianImage8bit, bmp);
int[] pixels = new int[bmp.getHeight() * bmp.getWidth()];
bmp.getPixels(pixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(),
bmp.getHeight());
if (bmp != null)
if (!bmp.isRecycled()) {
bmp.recycle();
}
int maxLap = -16777216;
for (int i = 0; i < pixels.length; i++) {
if (pixels[i] > maxLap) {
maxLap = pixels[i];
}
}
int soglia = -6118750;
if (maxLap < soglia || maxLap == soglia) {
return true;
} else {
return false;
}
} else {
return false;
}
} catch (NullPointerException e) {
return false;
} catch (OutOfMemoryError e) {
return false;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.