- Русские Блоги
- Python+OpenCV реализует прозрачные изображения PNG на изображениях JPG
- 1. Как читать изображение PNG 4 каналов обычно
- 2. Добавить альфа -канал в JPG -изображение
- 3. Сложите прозрачные изображения PNG с изображениями JPG
- Блог
- opencv: как преобразовать все черные пиксели в прозрачные и сохранить их в файле png
- Вопрос:
- Ответ №1:
- Ответ №2:
- Комментарии:
- Ответ №3:
Русские Блоги
Python+OpenCV реализует прозрачные изображения PNG на изображениях JPG
[Вопрос обнаружить] В процессе проектов обработки изображений мне часто нужно надзойти с одним изображением JPG на другой фоновый изображение JPG, чтобы достичь некоторых конкретных требований. Например, мы часто видим эффекты суперпозиции некоторых видеоэффектов в Дуйине и специальные эффекты ушей кошки на изображение лица человека. Мы можем использовать способ Python+OpenCV для достижения наложения между изображениями JPG, но больше прозрачных изображений PNG в реальных проектах наложены на изображения JPG. В этом случае традиционный метод суперпозиции JPG все еще применим, и появится исходное прозрачное изображение PNG. После суперпозиции он напрямую станет непрозрачным изображением JPG, которое не может достичь желаемых эффектов. Эта статья в основном объясняет, как использовать Python+OpenCV для реализации прозрачных изображений PNG на наложенные на изображения JPG.1. Как читать изображение PNG 4 каналов обычно
Чтобы решить вышеуказанные задачи, мы должны сначала понять разницу между изображениями JPG и изображениями PNG. Изображения JPG, считываемые методом Python+OpenCV, представляют собой три -канальные изображения BGR, и каждый канал представляет описание цвета. Изображение PNG представляет собой четырехканальное изображение. В дополнение к каналу BGR, есть также канал A, альфа -канал, описывающий прозрачность изображения. Однако следует отметить, что функция чтения изображения cv2.imread (), предоставленная OpenCV. Когда оно будет по умолчанию, чтение изображения PNG автоматически игнорирует альфа -канал, то есть изображение PNG напрямую становится изображением JPG. Поэтому нам нужно уделять особое внимание при чтении изображений PNG.
import cv2 img_path = 'imgs/demo.png' # Установите прозрачный путь изображения PNG # Img_bgr0 = cv2.imread (img_path, cv2.imread_color) # Помол # Img_bgr1 = cv2.imread (img_path) # метод считывания по умолчанию, результаты такие же, как и выше #img_gray = cv2.imread (img_path, cv2.imream_grale) # img_png = cv2.imread (img_path, cv2.imread_unchanged) # i i i i i i i i i i i i i i a и сохранить количество каналов без изменений.
2. Добавить альфа -канал в JPG -изображение
Прежде всего, суперпозиция между традиционными изображениями JPG накладывается на фоновое изображение, чтобы определить область с тем же размером, что и наложено. Например, изображение JPG 50*50*3 должно быть наложено на фоновое изображение JPG 100*100*3 размера, и вам необходимо указать площадь 50*50*3 на фоновом изображении, чтобы положить в бывшем. Кодовое шоу, как ниже:
import numpy as np import cv2 # Создать черное фоновое изображение 100*100*3 размер img_bg = np.zeros((100,100), dtype=np.uint8) img_bg = cv2.cvtColor(img_bg, cv2.COLOR_GRAY2BGR) # Создайте белый, чтобы быть наложенным с размером 50*50*3 img_white = np.ones((50,50), dtype=np.uint8) img_white = cv2.cvtColor(img_white, cv2.COLOR_GRAY2BGR) # Сложите белое изображение на фоновое изображение черного фона, а наложенное положение - верхний левый угол img_bg[:50,:50,:] = img_white # Cv2.imshow ('result', img_bg) # отображать полученное изображение результата после суперпозиции if cv2.waitKey(0) & 0xFF == 27: cv2.destroyAllWindows()
Когда изображения JPG наложены, их каналы 3 — 3, и проблем не будет. Однако, когда изображение канала PNG4 наложено на изображение канала JPG3, размер изображения не совпадает. Например, пространство 50*50*4 не может быть определена на изображении jpg 100*100*3, чтобы поместить изображение PNG. Чтобы решить эту проблему, нам необходимо увеличить альфа -канал для изображений JPG, которые можно понять, чтобы увеличить размер изображений JPG и сделать его достаточно для хранения изображений PNG. Кодовое шоу, как ниже:
import cv2 import numpy as np def add_alpha_channel(img): "" Добавить альфа -канал "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " B_channel, g_channel, r_channel = cv2.split (img) # канал изображения JPG Diping JPG alpha_channel = np.ones (b_channel.shape, dtype = b_channel.dtype) * 255 # создать альфа -канал img_new = cv2.merge ((b_channel, g_channel, r_channel, alpha_channel)) # return img_new
3. Сложите прозрачные изображения PNG с изображениями JPG
Перед наложенными изображениями нам нужно определить, какая позиция фонового изображения наложена. Здесь мы установили 2 точки координат в фоновом изображении: (x1, y1) и (x2, y2). Ниже координат.
Код суперпозиции изображения выглядит следующим образом:
img_bg[y2:y1,x1:x2] = img_white
Хорошо, после понимания основных принципов мы начинаем формировать формальное наложение изображения сейчас. Код выглядит следующим образом:
def merge_img(jpg_img, png_img, y1, y2, x1, x2): "" "" Наложенные прозрачные изображения PNG и изображения JPG Y1, y2, x1, x2 - это значение координат наложенного положения """ # Определите, было ли изображение JPG 4 канала if jpg_img.shape[2] == 3: jpg_img = add_alpha_channel(jpg_img) ''' Когда изображение наложено, оно может быть неправильным, потому что установлено положение суперпозиции, что приводит к тому, что граница изображения PNG превышает фоновое изображение JPG, и программа сообщает об ошибке Вот серия ограничений на позиции суперпозиции, которые могут соответствовать изображению PNG за пределами диапазона изображений JPG, и его все еще можно наложить нормально ''' yy1 = 0 yy2 = png_img.shape[0] xx1 = 0 xx2 = png_img.shape[1] if x1 < 0: xx1 = -x1 x1 = 0 if y1 < 0: yy1 = - y1 y1 = 0 if x2 >jpg_img.shape[1]: xx2 = png_img.shape[1] - (x2 - jpg_img.shape[1]) x2 = jpg_img.shape[1] if y2 > jpg_img.shape[0]: yy2 = png_img.shape[0] - (y2 - jpg_img.shape[0]) y2 = jpg_img.shape[0] # Получите альфа-значение, которое хочет покрыть изображение, удалить значение пикселя на 255 и сохранить значение между 0-1 alpha_png = png_img[yy1:yy2,xx1:xx2,3] / 255.0 alpha_jpg = 1 - alpha_png # Начать наложение for c in range(0,3): jpg_img[y1:y2, x1:x2, c] = ((alpha_jpg*jpg_img[y1:y2,x1:x2,c]) + (alpha_png*png_img[yy1:yy2,xx1:xx2,c])) return jpg_img
Здесь я говорю обо всем вышеперечисленном коде для интеграции. Полный код, уложенный изображению JPG на изображении JPG, выглядит следующим образом:
import cv2 import numpy as np def add_alpha_channel(img): "" Добавить альфа -канал "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " B_channel, g_channel, r_channel = cv2.split (img) # канал изображения JPG Diping JPG alpha_channel = np.ones (b_channel.shape, dtype = b_channel.dtype) * 255 # создать альфа -канал img_new = cv2.merge ((b_channel, g_channel, r_channel, alpha_channel)) # return img_new def merge_img(jpg_img, png_img, y1, y2, x1, x2): "" "" Наложенные прозрачные изображения PNG и изображения JPG Y1, y2, x1, x2 - это значение координат наложенного положения """ # Определите, было ли изображение JPG 4 канала if jpg_img.shape[2] == 3: jpg_img = add_alpha_channel(jpg_img) ''' Когда изображение наложено, оно может быть неправильным, потому что установлено положение суперпозиции, что приводит к тому, что граница изображения PNG превышает фоновое изображение JPG, и программа сообщает об ошибке Вот серия ограничений на позиции суперпозиции, которые могут соответствовать изображению PNG за пределами диапазона изображений JPG, и его все еще можно наложить нормально ''' yy1 = 0 yy2 = png_img.shape[0] xx1 = 0 xx2 = png_img.shape[1] if x1 < 0: xx1 = -x1 x1 = 0 if y1 < 0: yy1 = - y1 y1 = 0 if x2 >jpg_img.shape[1]: xx2 = png_img.shape[1] - (x2 - jpg_img.shape[1]) x2 = jpg_img.shape[1] if y2 > jpg_img.shape[0]: yy2 = png_img.shape[0] - (y2 - jpg_img.shape[0]) y2 = jpg_img.shape[0] # Получите альфа-значение, которое хочет покрыть изображение, удалить значение пикселя на 255 и сохранить значение между 0-1 alpha_png = png_img[yy1:yy2,xx1:xx2,3] / 255.0 alpha_jpg = 1 - alpha_png # Начать наложение for c in range(0,3): jpg_img[y1:y2, x1:x2, c] = ((alpha_jpg*jpg_img[y1:y2,x1:x2,c]) + (alpha_png*png_img[yy1:yy2,xx1:xx2,c])) return jpg_img if __name__ == '__main__': # Определить путь изображения img_jpg_path = 'imgs/0.jpg' # Reader может изменить путь файла сам по себе img_png_path = 'imgs/0.png' # Reader может изменить путь файла сам по себе # Прочтите изображение img_jpg = cv2.imread(img_jpg_path, cv2.IMREAD_UNCHANGED) img_png = cv2.imread(img_png_path, cv2.IMREAD_UNCHANGED) # Установка координат позиции наложенных позиций x1 = 560 y1 = 180 x2 = x1 + img_png.shape[1] y2 = y1 + img_png.shape[0] # Начать наложение res_img = merge_img(img_jpg, img_png, y1, y2, x1, x2) # Отображать изображение результатов cv2.imshow('result', res_img) # Сохраните изображение результата, читатели могут самостоятельно изменять путь к файлу cv2.imwrite('imgs/res.jpg', res_img) # Определить метод выхода программы: после нажатия на окно отображаемого изображения нажмите клавишу ESC, чтобы выйти из программы if cv2.waitKey(0) & 0xFF == 27: cv2.destroyAllWindows()
Попробуйте эффект с фотографиями моего хозяина ~
Наконец, я надеюсь, что эта статья может помочь друзьям, которые любят обработку изображений ~
Блог
opencv: как преобразовать все черные пиксели в прозрачные и сохранить их в файле png
#python #opencv
#python #opencv
Вопрос:
Изображение ниже, я хочу, чтобы все черные пиксели были прозрачными и сохранили его в файле png.
Ответ №1:
Вы можете сделать это быстро и векторизовано следующим образом:
import cv2 import numpy as np # Load image as Numpy array in BGR order na = cv2.imread('I5jKW.png') # Make a True/False mask of pixels whose BGR values sum to more than zero alpha = np.sum(na, axis=-1) > 0 # Convert True/False to 0/255 and change type to "uint8" to match "na" alpha = np.uint8(alpha * 255) # Stack new alpha layer with existing image to go from BGR to BGRA, i.e. 3 channels to 4 channels res = np.dstack((na, alpha)) # Save result cv2.imwrite('result.png', res)
1 Вы могли бы в равной степени использовать cv2.merge() вместо np.dstack() , и это, вероятно, быстрее.
2 Вы также можете использовать PIL / Pillow вместо функций OpenCV для чтения / сохранения изображений.
Ответ №2:
Вот еще один способ сделать это в Python / OpenCV / Numpy.
import cv2 import numpy as np # load image img = cv2.imread('girl_on_black.png') # threshold on black to make a mask color = (0,0,0) mask = np.where((img==color).all(axis=2), 0, 255).astype(np.uint8) # put mask into alpha channel result = img.copy() result = cv2.cvtColor(result, cv2.COLOR_BGR2BGRA) result[:, :, 3] = mask # save resulting masked image cv2.imwrite('girl_on_black_transparent.png', result) # display result, though it won't show transparency cv2.imshow("MASK", mask) cv2.imshow("RESULT", result) cv2.waitKey(0) cv2.destroyAllWindows()
Комментарии:
1. Отличное решение!
2. @Bin Chen Если мой ответ был полезен, пожалуйста, проголосуйте за него.
Ответ №3:
Изображения PNG с альфа-каналом можно сохранить с помощью этой функции. Для этого создайте 8-битное (или 16-битное) 4-канальное изображение BGRA, где альфа-канал идет последним. Для полностью прозрачных пикселей альфа должна быть установлена на 0, для полностью непрозрачных пикселей альфа должна быть установлена на 255/65535 (см. Пример кода ниже).
Прозрачное изображение поставляется с дополнительным каналом, который мы называем альфа-каналом и обозначаем BGRA в opencv. Все, что вам нужно сделать, это создать изображение маски в формате BGRA . Затем определите все черные пиксели на изображении и для этих черных пикселей назначьте альфа-каналу изображения маски значение 0.
Примечание: С opencv imshow или другими вы не сможете увидеть прозрачное изображение, потому что opencv не может отображать альфа-канал. Итак, вам нужно записать его imwrite в формате png.
Примечание: сделать прозрачным любой пиксель означает присвоить его альфа-каналу значение 0.
Вот вывод того, что я имею в виду:
Поскольку я не знаком с python, я закодировал шаги на C . Извините за это.
#include #include #include int main() < cv::Mat img = cv::imread("/ur/input/img.png",cv::IMREAD_COLOR); cv::Mat mask = cv::Mat::zeros(cv::Size(img.cols,img.rows),CV_8UC4); cv::namedWindow("Input",0); cv::namedWindow("Output",0); for(int i=0; ifor(int j=0; jif(img.at(cv::Point(i,j))[0] == 0 amp;amp; img.at(cv::Point(i,j))[1] == 0 amp;amp; img.at(cv::Point(i,j))[2] == 0) < mask.at(cv::Point(i,j))[0] = img.at(cv::Point(i,j))[0]; mask.at(cv::Point(i,j))[1] = img.at(cv::Point(i,j))[1]; mask.at(cv::Point(i,j))[2] = img.at(cv::Point(i,j))[2]; mask.at(cv::Point(i,j))[3] = 0; > else < mask.at(cv::Point(i,j))[0] = img.at(cv::Point(i,j))[0]; mask.at(cv::Point(i,j))[1] = img.at(cv::Point(i,j))[1]; mask.at(cv::Point(i,j))[2] = img.at(cv::Point(i,j))[2]; mask.at(cv::Point(i,j))[3] = 255; > > > cv::imshow("Input",img); cv::imshow("Output",mask); cv::imwrite("/ur/writing/dir/transparent.png",mask); cv::waitKey(0); return 0; >