Почему одни и те же пиксели имеют разные значения, используя PIL и Opencv? - PullRequest
0 голосов
/ 22 мая 2019

Я скачал случайное изображение из Интернета, открыл его, используя PIL.Image.open() и cv2.imread(), затем я проверил значения некоторых пикселей. Проблема в том, что я получил разные значения для одних и тех же пикселей, используя PIL и Opencv!
Это изображение, которое я пробовал:
enter image description here Вот что я сделал:

>>> import cv2
>>> from PIL import Image
>>> img = cv2.imread('img.jpg')
>>> im = Image.open('img.jpg')
>>> img[0][0]
>>> array([142, 152, 146], dtype=uint8)
>>> im.getpixel((0, 0))
>>> (138, 158, 131)

Значения R, G, B ((138! = 146), (158! = 152), (131! = 142)) как im, так и img не совпадают, хотя это один и тот же пиксель и одно и то же изображение!
Я просмотрел сообщения SO, обнаружил, что в этом сообщении говорит о той же проблеме, поэтому я использовал опубликованный код, чтобы еще раз проверить разницу:

from PIL import Image
import cv2
import sys
from hashlib import md5
import numpy as np

def hashIm(im):
    imP = np.array(Image.open(im))

    # Convert to BGR and drop alpha channel if it exists
    imP = imP[..., 2::-1]
    # Make the array contiguous again
    imP = np.array(imP)
    im = cv2.imread(im)

    diff = im.astype(int)-imP.astype(int)

    cv2.imshow('cv2', im)
    cv2.imshow('PIL', imP)
    cv2.imshow('diff', np.abs(diff).astype(np.uint8))
    cv2.imshow('diff_overflow', diff.astype(np.uint8))

    with open('dist.csv', 'w') as outfile:
        diff = im-imP
        for i in range(-256, 256):
            outfile.write('{},{}\n'.format(i, np.count_nonzero(diff==i)))

    cv2.waitKey(0)
    cv2.destroyAllWindows()

    return md5(im).hexdigest() + '   ' + md5(imP).hexdigest()

if __name__ == '__main__':
    print(hashIm('img.jpg'))

Полученные хэши разные, также разница между изображениями не черная!

Дополнительная информация:
- Os: Ubuntu 18.04
- Python: 3,6
- Opencv: opencv-python == 4.0.0.21
- PIL: Подушка == 5.4.1

Есть ли объяснение этому?

1 Ответ

1 голос
/ 22 мая 2019

Opencv хранит изображение в виде большого числа.

import cv2
cv_img = cv2.imread(img_path)
from PIL import Image
pil_img = Image.open(img_path)

Когда вы делаете cv_img[x][y], вы получаете доступ к y-му столбцу и x -ому ряду, но если вы делаете pil_img.getpixel((x,y)) подушку, то получаете доступ к x -ому столбцу и y -ому ряду.

Еще один фактор - возврат подушек в формате (R, G, B), когда opencv возвращает в формате (B, G, R).

Для меня cv_img[20][10] дает array([127, 117, 129], dtype=uint8). Проверьте здесь B = 127, G = 117, R = 129.

Но pil_img[10][20] дает (129, 117, 127). Проверьте здесь R = 129, G = 117, B = 127.

...