Интенсивность пикселей RGB-изображений и умножение на целые числа для просмотра оттенков серого - PullRequest
4 голосов
/ 12 июня 2019

У меня есть RGB-изображение, которое имеет 4 различных цвета: черный (0,0,0) в качестве фона, зеленый (106,136,93) синий (64,224,208) и коричневый (168,124,85).когда я читаю изображение в градациях серого и использую np.unique (), он возвращает огромный список интенсивностей пикселей.Но на самом деле, есть только 4 интенсивности, т.е. [0,1,2,3] черный, зеленый, синий и коричневый.

import cv2
import numpy as np

test = cv2.imread("test-BlackBG.png",0) #test image 

results = np.unique(test)     #returns [0,1,2,3,4,5,6,7,8...........132]
print(test.shape)             #returns (480, 640)
print(results)
cv2.imshow("image",test)
cv2.waitKey()
cv2.destroyAllWindows()

Ожидаемый результат: когда я умножу изображение на 85, оно должно показатьмне все 3 интенсивности в разных оттенках серого.

This is the Input image-

Ответы [ 3 ]

1 голос
/ 13 июня 2019

Существует ряд проблем с вашим вопросом и предположениями.


Вы не можете считать цвета с np.unique(image)

Вы не можете считать цвета на изображении с помощью np.unique(im). Давайте посмотрим, почему, сделав случайное изображение всего с 4 интенсивностями: 0,1,2 и 3.

import numpy as np
import cv2

# Ensure repeatable, deterministic randomness!
np.random.seed(42)

# Make a random image
im = np.random.randint(0,4,(480,640,3), dtype=np.uint8)

Это выглядит так, где каждая строка является триплетом RGB для одного пикселя:

array([[[2, 2, 3],
    [3, 2, 1],
    [2, 2, 0],
    ...,
    [3, 3, 2],
    [0, 0, 1],
    [1, 1, 1]],
    ...,
    [3, 3, 1],
    [2, 3, 0],
    [0, 1, 3]]], dtype=uint8)

Теперь, если вы попытаетесь получить уникальные цвета, подобные этим, это не сработает, потому что каждый цвет представляет собой комбинацию с 3 интенсивностями:

np.unique(im)    # prints: array([0, 1, 2, 3], dtype=uint8)

Принимая во внимание, что если вы хотите количество уникальных цветов, вам нужно искать количество уникальных комбинаций трех значений RGB / BGR:

np.unique(im.reshape(-1, im.shape[2]), axis=0)

, который дает вектор уникальных RGB / BGR-триплетов на изображении - каждая строка представляет собой уникальную комбинацию цветов:

array([[0, 0, 0],
       [0, 0, 1],
       [0, 0, 2],
       [0, 0, 3],
       [0, 1, 0],
       [0, 1, 1],
       [0, 1, 2],
       [0, 1, 3],
       [0, 2, 0],
       [0, 2, 1],
       [0, 2, 2],
       [0, 2, 3],
       [0, 3, 0],
       [0, 3, 1],
       [0, 3, 2],
       [0, 3, 3],
       [1, 0, 0],
       [1, 0, 1],
       [1, 0, 2],
       [1, 0, 3],
       [1, 1, 0],
       [1, 1, 1],
       [1, 1, 2],
       [1, 1, 3],
       [1, 2, 0],
       [1, 2, 1],
       [1, 2, 2],
       [1, 2, 3],
       [1, 3, 0],
       [1, 3, 1],
       [1, 3, 2],
       [1, 3, 3],
       [2, 0, 0],
       [2, 0, 1],
       [2, 0, 2],
       [2, 0, 3],
       [2, 1, 0],
       [2, 1, 1],
       [2, 1, 2],
       [2, 1, 3],
       [2, 2, 0],
       [2, 2, 1],
       [2, 2, 2],
       [2, 2, 3],
       [2, 3, 0],
       [2, 3, 1],
       [2, 3, 2],
       [2, 3, 3],
       [3, 0, 0],
       [3, 0, 1],
       [3, 0, 2],
       [3, 0, 3],
       [3, 1, 0],
       [3, 1, 1],
       [3, 1, 2],
       [3, 1, 3],
       [3, 2, 0],
       [3, 2, 1],
       [3, 2, 2],
       [3, 2, 3],
       [3, 3, 0],
       [3, 3, 1],
       [3, 3, 2],
       [3, 3, 3]], dtype=uint8)

Или, как простое число уникальных цветов:

len(np.unique(im.reshape(-1, im.shape[2]), axis=0))    # prints 64

Итак, для вашего изображения:

# Open image
im = cv2.imread('image.png',cv2.IMREAD_UNCHANGED)

# Count unique colours
len(np.unique(im.reshape(-1, im.shape[2]), axis=0)    # prints 790

Цветов больше, чем вы ожидаете

Почему у меня больше цветов, чем я ожидаю? Две наиболее распространенные причины:

  • изображение было сохранено в формате JPEG
  • есть текст или нарисованные фигуры, которые были сглажены

Давайте посмотрим, как сохранение в виде JPEG портит вам жизнь!

# Load image and count colours
im = cv2.imread('image.png',cv2.IMREAD_UNCHANGED)
len(np.unique(im.reshape(-1, im.shape[2]), axis=0))    # prints 790

# Save as JPEG
cv2.imwrite('temp.jpg',im)

# Reload and recount just the same
im = cv2.imread('temp.jpg',cv2.IMREAD_UNCHANGED)
len(np.unique(im.reshape(-1, im.shape[2]), axis=0))    # prints 4666 !!!

Как я могу палитрировать изображение - (уменьшить цвета до фиксированной палитры)?

Если вы хотите создать палитру своего изображения в соответствии со своей собственной палитрой, сначала вам нужно указать свою палитру в порядке BGR (!), чтобы соответствовать порядку OpenCV:

palette = np.array([
   [0,0,0],                # Black
   [93,136,106],           # Green
   [208,224,64],           # Blue
   [85,124,168]],          # Brown
   dtype=np.uint8)

Затем прочитайте ваше изображение, отбрасывая совершенно бессмысленный альфа-канал:

test = cv2.imread("image.png",cv2.IMREAD_COLOR)

Затем вычислите расстояние до каждой записи палитры для каждого пикселя:

distance = np.linalg.norm(test[:,:,None] - palette[None,None,:], axis=3)

Затем выберите любой из цветов палитры, ближайший к каждому пикселю:

palettised = np.argmin(distance, axis=2).astype(np.uint8)

Ваше изображение теперь находится в массиве palettised, и в каждом месте расположения пикселя хранится индекс ближайшего цвета в вашей палитре, поэтому, поскольку ваша палитра имеет 4 записи (0..3), все элементы вашего изображения 0, 1, 2 или 3.

Итак, теперь вы можете умножить на 85 с:

result = palettised * 85

enter image description here

0 голосов
/ 13 июня 2019

Я не совсем уверен, о чем вы просите, но чтобы определить интенсивность пикселей RGB изображений, вы можете изолировать каждый канал R, G и B, задав для других каналов значение 0. .

Исходное изображение

enter image description here

import cv2

image = cv2.imread('pikachu_smile.png')

blue = image.copy()
# Set green and red channels to 0
blue[:, :, 1] = 0
blue[:, :, 2] = 0

green = image.copy() 
# Set blue and red channels to 0
green[:, :, 0] = 0
green[:, :, 2] = 0

red = image.copy()
# Set blue and green channels to 0
red[:, :, 0] = 0
red[:, :, 1] = 0

cv2.imshow('blue', blue)
cv2.imshow('green', green)
cv2.imshow('red', red)

cv2.waitKey(0)

Изолированные синие (слева), зеленые (в центре) и красные (справа) каналы

enter image description here enter image description here enter image description here

Чтобы увеличить интенсивность определенного канала, вы можете добавить фиксированное значение ко всему каналу. Например, с зеленым каналом

green[:, :, 1] += 40

enter image description here

0 голосов
/ 13 июня 2019

Я думаю, что края отбрасывают это. Попробуйте написать функцию, чтобы установить пиксели, которые составляют края вашей фигуры, в точный цвет этой фигуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...