import cv2
def getImageVar(imgPath):
image = cv2.imread(imgPath);
img2gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
imageVar = cv2.Laplacian(img2gray, cv2.CV_64F).var()
return imageVar
真是人生苦短啊,核心代码就三行,简单解释下。
import cv2使用了一个著名的图像处理库 OpenCV,关于 OpenCV 的安装这里不多赘述,需要注意的是它依赖 numpy。
image = cv2.imread(imgPath)使用 OpenCV 提供的方法读取图片。img2gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)转化为灰度图。如下图:
原图是这样的:
cv2.Laplacian(img2gray, cv2.CV_64F)对图片用 3x3 拉普拉斯算子做卷积,这里的cv2.CV_64F就是拉普拉斯算子。
原理部分说过,拉普拉斯算子经常用于边缘检测,所以这里经过拉普拉斯算子之后,留下的都是检测到的边缘。上图经过这步处理之后是这样的:
可以看到这里图片人物大致还是比较清晰的。
cv2.Laplacian(img2gray, cv2.CV_64F).var()计算出方差,并最后返回。
上面那张图按这个计算出来时 3170 多,这个就是最后我们用来判断清晰度的值。
可以再找一张看看:
原图:
做灰度和经过拉普拉斯算子之后,可以看到人物部分已经不是很清晰了。
最后算出来的方差只有 530
剩下的工作就是根据整体图片质量确定阀值了。
局限性
通过上面的实操,我们知道这个算法的技巧在于设置合适的阀值,阈值太低会导致正常图片被误断为模糊图片,阈值太高会导致模糊图片被误判为正常图片。阀值依赖于你实际应用的业务场景,需要根据使用场景的不同做不同的定制。
真正的银弹并不存在。除了需要定个阀值外,有些图片可能会故意做个背景模糊或者背景虚化,这种图片很容易被误杀。
比如: