Почему цветные пиксели обнаруживаются в изображениях формата .png, но не обнаруживаются в изображениях формата .jpg?

У меня есть картинка с белым фоном, на котором есть красные, зеленые и синие линии. Красно-зеленая и синяя линии имеют исключительно следующие значения: (255,0,0), (0,255,0) и (0,0,255). Теперь изображение сохраняется как .png и как .jpg. Код должен работать в обоих форматах. Следующий код предназначен для определения цветов и возврата количества пикселей соответствующего цвета. Как .png код работает, как .jpg распознаются только зеленые пиксели, но к сожалению не все. Как можно распознать все пиксели всех трех цветов с помощью .jpg?

import cv2
import numpy as np

img = cv2.imread(r"...\red.jpg")
x,y,z = img.shape
print(x,y,z)

r = np.where((img == (0, 0, 255)).all(axis=2))
redarray = np.array(r)
red = np.size(redarray)
g = np.where((img == (0, 255, 0)).all(axis=2))
greenarray = np.array(g)
green = np.size(greenarray)
bl = np.where((img == (255, 0, 0)).all(axis=2))
bluearray = np.array(bl)
blue = np.size(bluearray)
       

print("red: ", red)
print("green: ", green)
print("blue: ", blue)

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
94
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Не видя изображений, изображения в формате jpeg сжимаются, и, если с ними не обращаться осторожно, значения пикселей не совпадают с эквивалентным изображением png.

Два подхода:

  1. После сохранения jpeg вы можете попробовать использовать более высокое разрешение/более низкое сжатие. Это может сработать. Это также увеличит размер файла.
  2. Вместо того, чтобы искать точные значения (например, red == (0, 0, 255)), ищите пиксели ниже некоторых порогов. Например, определите th=10 и найдите красные пиксели в диапазоне: green <= 0+th & blue <= 0+th & red >= 255-th.

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

Я хотел бы попробовать второй подход. Возможно ли применить эту «маску» в соответствующем выражении np.where(...)? В противном случае решение займет некоторое время...

MsX 22.12.2020 00:34

Согласно этому ответу, нарезка проще. Попробуйте mask = (img[:, :, 0] <= th) & (img[:, :, 1] <= th) & (img[:, :, 0] >= 255-th)

itaishz 22.12.2020 14:06

Обратите внимание, что для вашего вопроса, где у вас есть несколько линий на белом фоне, эта простая нарезка (с некоторыми пороговыми значениями), вероятно, сработает. Однако, если намерение состоит в том, чтобы масштабировать его до реальных изображений, по моему опыту, этого будет трудно достичь. Вероятно, вам нужно немного погуглить, как это сделать правильно. Например, преобразование изображения в пространство hsv, использование встроенных функций opencv2 и т. д.

itaishz 22.12.2020 14:10

Так и должно бытьmask = (img[:, :, 0] <= th) & (img[:, :, 1] <= th) & (img[:, :, 2] >= 255-th) не так ли?

MsX 22.12.2020 16:22

Да, последний img[: , :, i] должен быть с i=2, а не i=0, как в моем предыдущем комментарии. Извини за это.

itaishz 22.12.2020 16:27

Теперь я попытался маскировать в пространстве hsv. Теперь цвета действительно распознаются в обоих форматах. Однако, если я подсчитаю пиксели каждого из трех цветов, результат будет несколько отличаться для каждого из двух форматов. Но вряд ли этого можно избежать, не так ли?

MsX 22.12.2020 20:51

Давайте продолжим обсуждение в чате.

MsX 22.12.2020 20:53

PNG — это формат без потерь, а jpg — нет (, даже если вы используете качество 100 ).

Вот почему часть исходных «чистых» пикселей становится «нечистой» после сохранения и повторного считывания из формата jpeg.

Кстати, в вашем вопросе говорится:

Красно-зеленая и синяя линии имеют исключительно следующие значения: (255,0,0), (0,255,0) и (0,0,255)

но поведение opencv, а также ваш код - BGR. так красный, например, это (0,0,255)

Я знаю, это то, что я написал "а также ваш код"

Lior Cohen 22.12.2020 00:20

Другие вопросы по теме