Je dois écrire un scénario de test en python pour vérifier si une image jpg est en couleur ou en niveaux de gris. Quelqu'un peut-il me faire savoir s'il existe un moyen de le faire sans installer des bibliothèques supplémentaires comme opencv?
Réponse en expansion @gat:
import Image
def is_grey_scale(img_path):
img = Image.open(img_path).convert('RGB')
w,h = img.size
for i in range(w):
for j in range(h):
r,g,b = img.getpixel((i,j))
if r != g != b: return False
return True
En gros, vérifiez chaque pixel pour voir s’il est en niveaux de gris (R == G == B)
Peut être fait comme suit:
from scipy.misc import imread, imsave, imresize
image = imread(f_name)
if(len(image.shape)<3):
print 'gray'
Elif len(image.shape)==3:
print 'Color(RGB)'
else:
print 'others'
Pour un traitement plus rapide, il est préférable d'éviter les boucles sur chaque pixel, en utilisant ImageChops (mais aussi pour être sûr que l'image est vraiment en niveaux de gris, nous devons comparer les couleurs sur chaque pixel et ne pas utiliser la somme):
from PIL import Image,ImageChops
def is_greyscale(im):
"""
Check if image is monochrome (1 channel or 3 identical channels)
"""
if im.mode not in ("L", "RGB"):
raise ValueError("Unsuported image mode")
if im.mode == "RGB":
rgb = im.split()
if ImageChops.difference(rgb[0],rgb[1]).getextrema()[1]!=0:
return False
if ImageChops.difference(rgb[0],rgb[2]).getextrema()[1]!=0:
return False
return True
Une amélioration des performances pour des résultats rapides: comme beaucoup d'images ont une bordure noire ou blanche, vous pouvez vous attendre à une fin plus rapide en échantillonnant quelques points i, j aléatoires de im et les tester? Vous pouvez également utiliser l’arithmétique modulo pour parcourir les lignes de l’image. D'abord, nous échantillonnons (sans remplacement), disons 100 points aléatoires i, j; dans le cas peu probable où cela ne serait pas concluant, nous le numériserions linéairement.
Utilisation d’un itérateur personnalisé iterpixels (im). Je n'ai pas installé PIL, je ne peux donc pas le tester, voici le résumé:
import Image
def isColor(r,g,b): # use Tuple-unpacking to unpack pixel -> r,g,b
return (r != g != b)
class Image_(Image):
def __init__(pathname):
self.im = Image.open(pathname)
self.w, self.h = self.im.size
def iterpixels(nrand=100, randseed=None):
if randseed:
random.seed(randseed) # For deterministic behavior in test
# First, generate a few random pixels from entire image
for randpix in random.choice(im, n_Rand)
yield randpix
# Now traverse entire image (yes we will unwantedly revisit the nrand points once)
#for pixel in im.getpixel(...): # you could traverse rows linearly, or modulo (say) (im.height * 2./3) -1
# yield pixel
def is_grey_scale(img_path="lena.jpg"):
im = Image_.(img_path)
return (any(isColor(*pixel)) for pixel in im.iterpixels())
(Ma remarque originale est également vérifiée. Commencez par vérifier l'en-tête JPEG, offset 6: nombre de composants (1 = niveaux de gris, 3 = RVB). S'il s'agit de 1 = niveaux de gris, vous connaissez déjà la réponse sans avoir à inspecter les pixels individuels.)
Pourquoi n'utiliserions-nous pas le module ImageStat?
from PIL import Image, ImageStat
def is_grayscale(path="image.jpg")
im = Image.open(path).convert("RGB")
stat = ImageStat.Stat(im)
if sum(stat.sum)/3 == stat.sum[0]:
return True
else:
return False
stat.sum nous donne la somme de tous les pixels de la vue liste = [R, V, B], par exemple [568283302.0, 565746890.0, 559724236.0]. Pour une image en niveaux de gris, tous les éléments de la liste sont égaux.