imgrate/imgrate.py

85 lines
2.6 KiB
Python
Raw Normal View History

2018-01-01 15:33:10 +00:00
#!/usr/bin/env python3
import cv2
import numpy as np
2018-01-01 15:33:10 +00:00
from argparse import ArgumentParser
2018-02-24 19:21:27 +00:00
from functools import wraps
2018-02-24 19:30:02 +00:00
2018-02-24 19:21:27 +00:00
def image_required(fun):
@wraps(fun)
def wrapper(self, *args, **kwargs):
if self.image is None:
2018-02-24 19:30:02 +00:00
raise RuntimeError('Property {}.{} requires an image!'
2018-02-24 19:21:27 +00:00
.format(self.__class__.__name__, fun.__name__))
return fun(self, *args, **kwargs)
return wrapper
2018-01-01 15:33:10 +00:00
2018-02-24 19:30:02 +00:00
2018-02-24 19:04:44 +00:00
class imgrate:
def __init__(self, imgfile=None):
self.image = None
if imgfile: self.load_image(imgfile)
def load_image(self, imgfile):
image = cv2.imread(imgfile)
self.image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
@property
@image_required
def quality(self):
return self.laplacian * self.fdibm
2018-02-24 19:30:02 +00:00
@property
2018-02-24 19:21:27 +00:00
@image_required
2018-02-24 19:30:02 +00:00
def laplacian(self):
2018-02-24 19:04:44 +00:00
return cv2.Laplacian(self.image, cv2.CV_64F).var()
2018-02-24 19:30:02 +00:00
@property
2018-02-24 19:21:27 +00:00
@image_required
2018-02-24 19:04:44 +00:00
def fdibm(self):
F = np.fft.fft2(self.image)
Fcentered = np.fft.fftshift(F)
Fabs = np.abs(Fcentered)
Fmax = Fabs.max()
Th = np.count_nonzero(Fabs > Fmax/1000)
return Th / (F.shape[0] * F.shape[1])
2018-01-01 15:33:10 +00:00
2018-02-24 19:30:02 +00:00
2018-01-01 15:33:10 +00:00
if __name__ == '__main__':
2018-02-24 20:08:17 +00:00
from os import remove
from sys import exit
2018-04-14 16:24:14 +00:00
from signal import signal, SIGINT
signal(SIGINT, lambda a, b: exit('\nExiting!'))
2018-02-24 20:08:17 +00:00
2018-02-24 20:03:36 +00:00
def parse_arguments():
2018-02-24 20:20:47 +00:00
ap = ArgumentParser(description='Find the best quality one among similar images.'
'Note: image dimensions should match!')
2018-02-24 20:03:36 +00:00
ap.add_argument('images', type=str, nargs='+', help='')
2018-02-24 20:08:17 +00:00
ap.add_argument('-d', '--delete', action='store_true', help='Delete all but the best quality image.')
2018-02-24 20:12:14 +00:00
ap.add_argument('-q', '--quiet', action='store_true', help='Print quality measurements only.')
ap.add_argument('-m', '--method', type=str, default='quality', help='Select quality measurement to use.')
2018-02-24 20:03:36 +00:00
return ap.parse_args()
2018-01-01 15:33:10 +00:00
2018-02-24 19:41:57 +00:00
2018-02-24 20:03:36 +00:00
def run(args):
try: ratings = {image: getattr(imgrate(image), args.method) for image in args.images}
except AttributeError: exit('Invalid --method option!')
2018-02-24 20:03:36 +00:00
maximum = max(ratings, key=ratings.get)
for rating in ratings.keys():
2018-02-24 20:12:14 +00:00
if args.quiet:
print(ratings[rating])
else:
maxmark = '*' if rating == maximum and len(ratings) > 1 else ' '
print('{}imgrate("{}") = {}'.format(maxmark, rating, ratings[rating]))
2018-02-24 20:03:36 +00:00
2018-02-24 20:08:17 +00:00
if args.delete:
[remove(image) for image in ratings if image != maximum]
2018-02-24 20:03:36 +00:00
run(parse_arguments())