Як перевірити, чи файл є дійсним файлом зображення?


105

Зараз я використовую PIL.

from PIL import Image
try:
    im=Image.open(filename)
    # do stuff
except IOError:
    # filename not an image file

Однак, хоча це достатньо охоплює більшість випадків, деякі файли зображень, такі як xcf, svg та psd, не виявляються. Файли Psd видає виняток OverflowError.

Чи є якимось чином і я міг би їх включити?


21
Не особливо поширена практика закривати дублікати на різних мовах. Якщо ви не можете знайти жодних інших питань, пов'язаних з Python, залиште його відкритим, оскільки можуть бути конкретні рішення для Python, які люди хочуть опублікувати, але не зробили це питання, яке ви поставили.
Паоло Бергантіно,

так, по-перше, я дуже сподівався на пітона, про який я не знав: P, а потім, як зазначив Бен, просто магічні цифри не підтверджують все зображення.
Сухой

@Sujoy, перевірити ціле зображення майже неможливо, якщо ви вже не маєте його копії, тому що комп'ютер не може визначити різницю між правильним кольоровим пікселем та накресленим набором 1s та 0s, якщо весь контроль (магічні числа) правильні.
DevinB

@devinb, домовились, я просто отримаю магічні цифри і з цим буду займатися, якщо хтось інший не придумає щось краще, щоб зателефонувати на рефактора :)
Sujoy

xcf та psd насправді не є зображеннями, вони є файлами проектів, які містять (часто багато) зображень ... ви, мабуть, могли б зробити випадок для svg, хоча.
mgalgs

Відповіді:


11

Багато разів перші пара символів будуть чарівним числом для різних форматів файлів. Ви можете перевірити це на додаток до перевірки винятків вище.


10
Цього буде недостатньо, якщо він справді тестує на "дійсні" зображення; наявність магічного номера не гарантує, наприклад, що файл не був усічений.
Бен Бланк

1
чудова порада, тепер мені просто потрібно розібратися, що це за цифри. дякую :)
Sujoy

@ben, ой, я ще про це не думав. це хороший момент
Sujoy

@Ben, як би ви очікували, що бібліотека може зробити висновок про врізаний файл?
DevinB

6
@Ben Blank: Щоправда, але вирішувати проблему на 99% шляху часто краще, ніж взагалі не вирішувати.
Брайан Р. Бонді

206

Я щойно знайшов вбудований модуль imghdr . З документації python:

Модуль imghdr визначає тип зображення, що міститься у файлі чи байтовому потоці.

Ось як це працює:

>>> import imghdr
>>> imghdr.what('/tmp/bass')
'gif'

Використання модуля набагато краще, ніж повторне виконання аналогічних функцій


2
так, imghdr працює для більшості форматів зображень, але не для всіх. відповідно до моєї оригінальної проблеми зі файлами svg, xcf та psd, вони також не виявлені в imghdr
Sujoy

2
Ваша відповідь насправді краща, дякую. Як хтось вище сказав ... але вирішувати проблему 99% способу часто краще, ніж взагалі не вирішувати ..
RinkyPinku

2
Варто зазначити: imghdr.what(path)повертається, Noneякщо дані pathне розпізнаються тип файлу зображення. Список в даний час було розпізнати типів зображення: RGB , GIF , PBM , платиноїди , частини на мільйон , кальцит , Раст , XBM , JPEG , BMP , PNG , WebP , EXR .
patryk.beza

1
Будь обережний! Дійсний hdr не означає дійсне зображення (наприклад, байти зображень можуть бути зашифровані!)
Filippo Mazza

1
За коментарем @FilippoMazza я можу підтвердити, що неправильне зображення, яке було відрізане під час передачі, може пройти цей тест, але зламається, коли PIL намагатиметься його прочитати.
kevinmicke

47

На додаток до того, що пропонує Брайан, ви можете використовувати метод підтвердження PIL, щоб перевірити, чи файл порушений.

ім.перевірити ()

Спроби визначити, чи файл порушений, не фактично розшифровуючи дані зображення. Якщо цей метод виявить якісь проблеми, він може спричинити винятки. Цей метод працює лише на щойно відкрите зображення; якщо зображення вже завантажено, результат не визначений. Крім того, якщо вам потрібно завантажити зображення після використання цього методу, потрібно знову відкрити файл зображення. Атрибути


ну головна проблема полягає в тому, що файли svg, xcf та psd неможливо відкрити за допомогою Image.open (), отже, немає шансів на перевірку за допомогою im.verify ()
Sujoy

16
Мій бог, документація PIL жахлива. Що саме є "підходящим винятком"?
Timmmm

Ось посилання на документацію подушки для Image.verify () . На жаль, це не краще, і, схоже, вони просто підняли абзац вище, не додаючи нічого.
Двобітний алхімік

Я бачив перевірити підняття SyntaxError для пошкоджених файлів PNG
Карл

чи є спосіб перевірити "З дійсно розшифровкою даних зображення"?
Тревор Бойд Сміт

7

Додатково до PILперевірки зображення ви також можете додати перевірку розширення імені файлу таким чином:

filename.lower().endswith(('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif'))

Зауважте, що це перевіряє, чи має ім'я файлу дійсне розширення зображення, воно насправді не відкриває зображення, щоб побачити, чи це дійсне зображення, тому вам потрібно додатково використовувати PILабо одну з бібліотек, запропоновану в інших відповідях.


Що робити, якщо розширення у файлах неправильні? Наприклад, текстовий файл зберігається з розширенням .jpg або навпаки.
hafiz031

1
@ hafiz031 Щоб отримати фактичний формат, ви можете зробити, from PIL import Image img = Image.open(filename) print(img.format)а потім перевірити його так:img.format.lower() in ['png', 'jpg', 'jpeg', 'tiff', 'bmp', 'gif']
tsveti_iko

На жаль, це не спрацювало для мене. Він досі ідентифікує пошкоджене зображення як зображення JPEG. Нарешті мені вдалося впоратися з цією справою в цьому випадку (я використовую OpenCV): stackoverflow.com/a/63421847/6907424
hafiz031

6

Оновлення

Я також реалізував таке рішення в своєму скрипті Python тут, на GitHub .

Я також переконався, що пошкоджені файли (jpg) часто не є "зламаними" зображеннями, тобто пошкоджений файл зображення іноді залишається законним файлом зображення, оригінальне зображення втрачається або змінюється, але ви все ще можете завантажити його без помилок. Але, усічення файлів викликає завжди помилки.

Закінчити оновлення

Ви можете використовувати модуль Python Pillow (PIL) у більшості форматів зображень, щоб перевірити, чи файл є дійсним та неушкодженим файлом зображення.

У випадку, якщо ви прагнете виявити також пошкоджені зображення, @Nadia Alramli правильно пропонує im.verify()метод, але це не виявляє всіх можливих дефектів зображення , наприклад, im.verifyне виявляє усічені зображення (що більшість глядачів часто завантажують із сірою областю).

Подушка також може виявити такі типи дефектів, але вам доведеться застосувати маніпулювання зображенням або декодування / перекодування зображення в або для запуску перевірки. Нарешті, я пропоную скористатися цим кодом:

try:
  im = Image.load(filename)
  im.verify() #I perform also verify, don't know if he sees other types o defects
  im.close() #reload is necessary in my case
  im = Image.load(filename) 
  im.transpose(PIL.Image.FLIP_LEFT_RIGHT)
  im.close()
except: 
  #manage excetions here

У разі дефектів зображення цей код спричинить виняток. Зверніть увагу, що im.verify приблизно в 100 разів швидше, ніж виконання маніпуляцій із зображенням (і я думаю, що фліп - це одна з дешевих трансформацій). За допомогою цього коду ви збираєтеся перевірити набір зображень із швидкістю близько 10 Мбіт / сек із стандартною подушкою або 40 Мбіт / с за допомогою модуля Pillow-SIMD (сучасний процесор 2,5 ГГц x86_64).

Для інших форматів psd , xcf , .. ви можете використовувати Imagemagick обгортку Wand , код такий:

im = wand.image.Image(filename=filename)
temp = im.flip;
im.close()

Але, з моїх експериментів, Wand не виявляє усічені зображення, я думаю, що він завантажує відсутні частини, як сіру область, не вимагаючи.

Я помічаю, що Imagemagick має зовнішню ідентифікацію команди, яка могла б виконати роботу, але я не знайшов способу викликати цю функцію програмно, і я не перевіряв цей маршрут.

Я пропоную завжди проводити попередню перевірку, перевіряти розмір файлів, щоб він не дорівнював нулю (або дуже малий), дуже дешева ідея:

statfile = os.stat(filename)
filesize = statfile.st_size
if filesize == 0:
  #manage here the 'faulty image' case

5

В Linux ви можете використовувати python-magic ( http://pypi.python.org/pypi/python-magic/0.1 ), який використовує libmagic для ідентифікації форматів файлів.

AFAIK, libmagic заглядає у файл і намагається розповісти вам більше про нього, а не лише про формат, як, наприклад, розміри растрових зображень, версію формату тощо. Отже, ви можете бачити це як поверхневий тест на "дійсність".

Для інших визначень "дійсних" можливо вам доведеться написати власні тести.


5

Ви можете використати прив'язки Python до лібмагічних, пітон-магічних, а потім перевірити типи mime. Це не скаже вам, чи файли пошкоджені чи неушкоджені, але він повинен мати можливість визначати, який тип зображення це.


3

Ну, я не знаю про внутрішню частину PSD, але я, звичайно, знаю, що фактично svg не є файлом зображення, - він заснований на xml, так що він, по суті, є звичайний текстовий файл.


ага, ти маєш рацію. це xml однак він містить деякі вбудовані в нього дані зображення.
Сухой

2

Один із варіантів - використовувати filetypeпакет.

Установка

python -m pip install filetype

Переваги

  1. Швидкий: чи працює це, завантажуючи перші кілька байтів вашого зображення ( перевірте магічне число )
  2. Підтримує різні типи mime: зображення, відео, шрифти, аудіо, архіви.

Приклад рішення

import filetype

filename = "/path/to/file.jpg"

if filetype.image(filename):
    print(f"{filename} is a valid image...")
elif filetype.video(filename):
    print(f"{filename} is a valid video...")

Додаткова інформація на офіційному репо: https://github.com/h2non/filetype.py


1

Чи перевіряє розширення файлів прийнятне чи ви намагаєтеся підтвердити, що дані представляють файл зображення?

Якщо ви можете перевірити розширення файлу, звичайний вираз або просте порівняння можуть задовольнити вимогу.


достатньо просто перевірити розширення, оскільки ви можете перейменувати txt-файл у jpg або щось подібне. Я здогадуюсь, якщо я не можу знайти рішення, лише тоді я буду використовувати перевірку розширень для xcf та svg
Sujoy

Зрозуміло, що я просто сподівався на деяке уточнення, перш ніж приступити до розробки рішення, яке може краще відповідати вашим потребам. Дякую!
doomspork

-1
format = [".jpg",".png",".jpeg"]
 for (path,dirs,files) in os.walk(path):
     for file in files:
         if file.endswith(tuple(format)):
             print(path)
             print ("Valid",file)
         else:
             print(path)
             print("InValid",file)

У коді є деякі проблеми з відступом, і він не працює належним чином. Також розгляньте можливість додавання пояснень, чому і як ваш код вирішує проблему. Відповіді, кодовані лише кодом, не можуть бути корисними для майбутніх читачів, які приїжджають сюди.
Tomerikoo

Тут ми використовували метод Agrparser.
rObinradOO
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.