У меня есть картинка с белым фоном, на котором есть красные, зеленые и синие линии. Красно-зеленая и синяя линии имеют исключительно следующие значения: (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)
Не видя изображений, изображения в формате jpeg сжимаются, и, если с ними не обращаться осторожно, значения пикселей не совпадают с эквивалентным изображением png.
Два подхода:
red == (0, 0, 255)
), ищите пиксели ниже некоторых порогов. Например, определите th=10
и найдите красные пиксели в диапазоне: green <= 0+th & blue <= 0+th & red >= 255-th
.Извините, у меня нет рабочего кода под этим ответом, дайте мне знать, если вам нужна дополнительная помощь с маскировкой.
Согласно этому ответу, нарезка проще. Попробуйте mask = (img[:, :, 0] <= th) & (img[:, :, 1] <= th) & (img[:, :, 0] >= 255-th)
Обратите внимание, что для вашего вопроса, где у вас есть несколько линий на белом фоне, эта простая нарезка (с некоторыми пороговыми значениями), вероятно, сработает. Однако, если намерение состоит в том, чтобы масштабировать его до реальных изображений, по моему опыту, этого будет трудно достичь. Вероятно, вам нужно немного погуглить, как это сделать правильно. Например, преобразование изображения в пространство hsv, использование встроенных функций opencv2 и т. д.
Так и должно бытьmask = (img[:, :, 0] <= th) & (img[:, :, 1] <= th) & (img[:, :, 2] >= 255-th)
не так ли?
Да, последний img[: , :, i]
должен быть с i=2
, а не i=0
, как в моем предыдущем комментарии. Извини за это.
Теперь я попытался маскировать в пространстве hsv. Теперь цвета действительно распознаются в обоих форматах. Однако, если я подсчитаю пиксели каждого из трех цветов, результат будет несколько отличаться для каждого из двух форматов. Но вряд ли этого можно избежать, не так ли?
Давайте продолжим обсуждение в чате.
PNG — это формат без потерь, а jpg — нет (, даже если вы используете качество 100 ).
Вот почему часть исходных «чистых» пикселей становится «нечистой» после сохранения и повторного считывания из формата jpeg.
Кстати, в вашем вопросе говорится:
Красно-зеленая и синяя линии имеют исключительно следующие значения: (255,0,0), (0,255,0) и (0,0,255)
но поведение opencv, а также ваш код - BGR. так красный, например, это (0,0,255)
Я знаю, это то, что я написал "а также ваш код"
Я хотел бы попробовать второй подход. Возможно ли применить эту «маску» в соответствующем выражении np.where(...)? В противном случае решение займет некоторое время...