• python之 ffmpeg+opencv绿幕抠图,蒙版绿幕抠图,透明化处理,PIL检测图片是否包含透明通道


    目录

    OpenCV-Python实现绿幕图像抠图

    python利用蒙版批量抠图并实现透明化

    jpeg格式图片进行批量背景透明化处理

    PIL检测图片是否包含透明通道


    OpenCV-Python实现绿幕图像抠图

    • boy.png:最终结果保存的图片

    (1)input.jpg图片:

    (2)执行代码, 

     完整代码: 

    1. # -*-coding:utf-8-*-
    2. import cv2 as cv
    3. import numpy as np
    4. """
    5. OpenCV-Python实现绿幕图像抠图
    6. """
    7. def image_matting(image_path: str):
    8. # todo 读取并转换图片格式
    9. img = cv.imread(image_path, cv.IMREAD_COLOR)
    10. cv.imshow('input', img) # 将图像在特定的窗口进行显示
    11. hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV) # Opencv里的颜色空间转换函数,可以实现RGB颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像,参数CV_RGB2GRAY是RGB到gray
    12. # cv.imshow('hsv', hsv)
    13. # todo 确定绿色范围
    14. """
    15. cv.inRange(src, lowerb, upperb):根据像素的范围进行过滤,把符合像素范围的保留,赋值0,黑色;不符合的赋值255,白色。
    16. src:需要处理的图像
    17. lowerb:最小像数值
    18. upperb:最大像素值
    19. """
    20. mask = cv.inRange(hsv, (35, 43, 46), (77, 255, 255))
    21. # cv.imshow('cc', mask)
    22. # todo 确定非绿色范围
    23. mask = cv.bitwise_not(mask) # 非:cv.bitwise_not(img),将图像按位取反操作。
    24. # todo 通过掩码控制的按位与运算锁定绿色区域
    25. result = cv.bitwise_and(img, img, mask=mask) # 只在mask区域做与运算 与:cv.bitwise_and(img1,img2),两幅图像按位进行与操作;
    26. # cv.imshow('mask', mask)
    27. # todo 显示图片验证结果
    28. cv.imshow('result', result)
    29. # 保存带有透明通道的png图片, 有了这种素材之后,就可以给这张图片替换任意背景了
    30. cv.imwrite('boy.png', result)
    31. cv.waitKey(0)
    32. cv.destroyAllWindows()
    33. # canny边缘检测 和轮廓提提取方法
    34. if __name__ == '__main__':
    35. path = 'img.jpg'
    36. image_matting(path)

    (3)可以看到执行结果, 

    而且,最终结果保存的图片boy.png为:

      

    python利用蒙版批量抠图并实现透明化

    步骤:

    • 如果input图片为jpeg格式图片,那么就需要进行第一步操作 :将tt文件夹里的jpeg格式图片“imput.jpeg”先转化为png格式。
    • 利用蒙版批量抠图并实现透明化

     (1)将tt文件夹里的jpeg格式图片“imput.jpeg”先转化为png格式,

     代码为:

    1. def change_png():
    2. '''将批量的jpeg图片转为png格式'''
    3. file_path = "tt"
    4. count = 0
    5. files = os.listdir(file_path)
    6. for file in files:
    7. if file.endswith('jpeg'):
    8. # 要指明重命名之后的路径
    9. src = os.path.join(file_path, file)
    10. r_name = file.split('.')[0] + '.png'
    11. dct = os.path.join(file_path, r_name)
    12. os.rename(src, dct)
    13. count = count + 1
    14. print('count:', count)
    15. if __name__ == "__main__":
    16. change_png()

     可以看到转换结果是,

    (2)得到图片的蒙版mask,利用蒙版批量抠图并实现透明化,

    1. import cv2, os
    2. from PIL import Image
    3. import numpy as np
    4. def change_png():
    5. '''将批量的jpeg图片转为png格式'''
    6. file_path = "tt"
    7. count = 0
    8. files = os.listdir(file_path)
    9. for file in files:
    10. if file.endswith('jpeg'):
    11. # 要指明重命名之后的路径
    12. src = os.path.join(file_path, file)
    13. r_name = file.split('.')[0] + '.png'
    14. dct = os.path.join(file_path, r_name)
    15. os.rename(src, dct)
    16. count = count + 1
    17. print('count:', count)
    18. def get_mask():
    19. '''得到图片的蒙版mask'''
    20. file_path = "tt"
    21. count = 0
    22. files = os.listdir(file_path)
    23. for file in files:
    24. image_path = file_path + '/' + file
    25. print(image_path)
    26. # todo 读取并转换图片格式
    27. img = cv2.imread(image_path, cv2.IMREAD_COLOR)
    28. # cv2.imshow('input', img) # 将图像在特定的窗口进行显示
    29. hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # Opencv里的颜色空间转换函数,可以实现RGB颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像,参数CV_RGB2GRAY是RGB到gray
    30. # cv.imshow('hsv', hsv)
    31. # todo 确定绿色范围
    32. """
    33. cv.inRange(src, lowerb, upperb):根据像素的范围进行过滤,把符合像素范围的保留,赋值0,黑色;不符合的赋值255,白色。
    34. src:需要处理的图像
    35. lowerb:最小像数值
    36. upperb:最大像素值
    37. """
    38. mask = cv2.inRange(hsv, (35, 43, 46), (77, 255, 255))
    39. # cv.imshow('cc', mask)
    40. # todo 确定非绿色范围
    41. mask = cv2.bitwise_not(mask) # 非:cv.bitwise_not(img),将图像按位取反操作。
    42. # todo 通过掩码控制的按位与运算锁定绿色区域
    43. result = cv2.bitwise_and(img, img, mask=mask) # 只在mask区域做与运算 与:cv.bitwise_and(img1,img2),两幅图像按位进行与操作;
    44. # cv2.imshow('mask22', mask)
    45. cv2.imwrite('mask/' + file.split('.')[0] +'_mask.jpg' , mask)
    46. count += 1
    47. print('count:', count)
    48. class UnsupportedFormat(Exception):
    49. def __init__(self, input_type):
    50. self.t = input_type
    51. def __str__(self):
    52. return "不支持'{}'模式的转换,请使用为图片地址(path)、PIL.Image(pil)或OpenCV(cv2)模式".format(self.t)
    53. class MatteMatting():
    54. def __init__(self, original_graph, mask_graph, input_type='path'):
    55. """
    56. 将输入的图片经过蒙版转化为透明图构造函数
    57. :param original_graph:输入的图片地址、PIL格式、CV2格式
    58. :param mask_graph:蒙版的图片地址、PIL格式、CV2格式
    59. :param input_type:输入的类型,有path:图片地址、pil:pil类型、cv2类型
    60. """
    61. if input_type == 'path':
    62. self.img1 = cv2.imread(original_graph)
    63. self.img2 = cv2.imread(mask_graph)
    64. elif input_type == 'pil':
    65. self.img1 = self.__image_to_opencv(original_graph)
    66. self.img2 = self.__image_to_opencv(mask_graph)
    67. elif input_type == 'cv2':
    68. self.img1 = original_graph
    69. self.img2 = mask_graph
    70. else:
    71. raise UnsupportedFormat(input_type)
    72. @staticmethod
    73. def __transparent_back(img):
    74. """
    75. :param img: 传入图片地址
    76. :return: 返回替换白色后的透明图
    77. """
    78. img = img.convert('RGBA')
    79. L, H = img.size
    80. color_0 = (255, 255, 255, 255) # 要替换的颜色
    81. for h in range(H):
    82. for l in range(L):
    83. dot = (l, h)
    84. color_1 = img.getpixel(dot)
    85. if color_1 == color_0:
    86. color_1 = color_1[:-1] + (0,)
    87. img.putpixel(dot, color_1)
    88. return img
    89. def save_image(self, path, mask_flip=False):
    90. """
    91. 用于保存透明图
    92. :param path: 保存位置
    93. :param mask_flip: 蒙版翻转,将蒙版的黑白颜色翻转;True翻转;False不使用翻转
    94. """
    95. if mask_flip:
    96. img2 = cv2.bitwise_not(self.img2) # 黑白翻转
    97. image = cv2.add(self.img1, img2)
    98. image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) # OpenCV转换成PIL.Image格式
    99. img = self.__transparent_back(image)
    100. img.save(path)
    101. @staticmethod
    102. def __image_to_opencv(image):
    103. """
    104. PIL.Image转换成OpenCV格式
    105. """
    106. img = cv2.cvtColor(np.asarray(image), cv2.COLOR_RGB2BGR)
    107. return img
    108. @staticmethod
    109. def __image_to_opencv(image):
    110. """
    111. PIL.Image转换成OpenCV格式
    112. """
    113. img = cv2.cvtColor(np.asarray(image), cv2.COLOR_RGB2BGR)
    114. return img
    115. if __name__ == '__main__':
    116. # change_png()
    117. get_mask()
    118. file_path = "tt"
    119. count = 0
    120. files = os.listdir(file_path)
    121. for file in files:
    122. image_path = file_path + '/' + file
    123. mask_path = 'mask/'+ file.split('.')[0] +'_mask.jpg'
    124. output_path = 'output/'+ file.split('.')[0] +'_output.png'
    125. mm = MatteMatting(image_path, mask_path)
    126. mm.save_image(output_path, mask_flip=True) # mask_flip是指蒙版翻转,即把白色的变成黑色的,黑色的变成白色的
    127. count += 1
    128. print('count:', count)

    执行截图:

     (3)可以看到执行的结果,

     

     

    jpeg格式图片进行批量背景透明化处理

    步骤:

    • 如果input图片为jpeg格式图片,那么就需要进行第一步操作 :将tt文件夹里的jpeg格式图片“imput.jpeg”先转化为png格式。
    • 批量背景透明化处理

    (1)将tt文件里的jpeg格式图片“imput.jpeg”先转化为png格式,

     代码为:

    1. def change_png():
    2. '''将批量的jpeg图片转为png格式'''
    3. file_path = "tt"
    4. count = 0
    5. files = os.listdir(file_path)
    6. for file in files:
    7. if file.endswith('jpeg'):
    8. # 要指明重命名之后的路径
    9. src = os.path.join(file_path, file)
    10. r_name = file.split('.')[0] + '.png'
    11. dct = os.path.join(file_path, r_name)
    12. os.rename(src, dct)
    13. count = count + 1
    14. print('count:', count)
    15. if __name__ == "__main__":
    16. change_png()

     可以看到转换结果是,

     (2)绿色背景png格式图片背景透明化处理

    补充:可以用这个网页RGB(255,0,255),#FF00FF 颜色查询,颜色梯度,色彩搭配,色盲模拟 - RGB颜色查询 - 在线工具 - 字客网来将颜色转换为rgb值

     代码:

    1. import os
    2. from PIL import Image
    3. '''绿色背景png格式图片背景透明化处理'''
    4. class Transcolor():
    5. def __init__(self):
    6. # 最后一位表示透明度
    7. self.color_map = {
    8. 'white': (255, 255, 255, 0),
    9. 'black': (0, 0, 0, 0),
    10. 'green': (87, 211, 57, 0)
    11. }
    12. def process(self, image_file, old_bk, new_bk, text_color):
    13. '''将图像特定颜色改为新颜色,前文改为设定颜色或者原始颜色'''
    14. img = Image.open(image_file).convert("RGBA")
    15. datas = img.getdata()
    16. newData = []
    17. for item in datas:
    18. if self.is_around(item, old_bk):
    19. newData.append(new_bk)
    20. else:
    21. newData.append(text_color if text_color else item)
    22. img.putdata(newData)
    23. return img
    24. def transparent(self, image_file, bk_color='green', text_color=None):
    25. # 透明化
    26. bk = self.formulate(bk_color)
    27. text_color = self.formulate(text_color) if text_color else None
    28. return self.process(image_file, bk, (0, 0, 0, 0), text_color)
    29. def is_around(self, color1, color2):
    30. for i in range(3):
    31. if abs(color1[i] - color2[i]) > 30:
    32. return False
    33. return True
    34. def formulate(self, var): # 格式检查
    35. if var in self.color_map.keys():
    36. return self.color_map[var]
    37. for n, i in enumerate(var):
    38. if i < 0 or i > 255 or n >= 4:
    39. print('Error:请输入white|black|phote_w|(220,220,220,0)RGBA形式')
    40. exit(1)
    41. return var
    42. if __name__ == "__main__":
    43. t = Transcolor()
    44. photo_dir = 'tt'
    45. for i in os.listdir(photo_dir):
    46. if os.path.splitext(i)[1].lower() in ['.jpg', '.png', '.jpeg', '.bmp']:
    47. path = os.path.join(photo_dir, i)
    48. t.transparent(path).save(path)

    (3)可以看到背景透明化处理之后的结果是,

     (4)完整代码:

    1. import os
    2. from PIL import Image
    3. '''绿色背景jpeg格式图片进行批量背景透明化处理'''
    4. def change_png():
    5. '''将批量的jpeg图片转为png格式'''
    6. file_path = "tt"
    7. count = 0
    8. files = os.listdir(file_path)
    9. for file in files:
    10. if file.endswith('jpeg'):
    11. # 要指明重命名之后的路径
    12. src = os.path.join(file_path, file)
    13. r_name = file.split('.')[0] + '.png'
    14. dct = os.path.join(file_path, r_name)
    15. os.rename(src, dct)
    16. count = count + 1
    17. print('count:', count)
    18. class Transcolor():
    19. def __init__(self):
    20. # 最后一位表示透明度
    21. self.color_map = {
    22. 'white': (255, 255, 255, 0),
    23. 'black': (0, 0, 0, 0),
    24. 'green': (35, 43, 46, 0)
    25. }
    26. def process(self, image_file, old_bk, new_bk, text_color):
    27. '''将图像特定颜色改为新颜色,前文改为设定颜色或者原始颜色'''
    28. img = Image.open(image_file).convert("RGBA")
    29. datas = img.getdata()
    30. newData = []
    31. for item in datas:
    32. if self.is_around(item, old_bk):
    33. newData.append(new_bk)
    34. else:
    35. newData.append(text_color if text_color else item)
    36. img.putdata(newData)
    37. return img
    38. def transparent(self, image_file, bk_color='green', text_color=None):
    39. '''透明化'''
    40. bk = self.formulate(bk_color)
    41. text_color = self.formulate(text_color) if text_color else None
    42. return self.process(image_file, bk, (0, 0, 0, 0), text_color)
    43. def is_around(self, color1, color2):
    44. for i in range(3):
    45. if abs(color1[i] - color2[i]) > 30:
    46. return False
    47. return True
    48. def formulate(self, var): # 格式检查
    49. if var in self.color_map.keys():
    50. return self.color_map[var]
    51. for n, i in enumerate(var):
    52. if i < 0 or i > 255 or n >= 4:
    53. print('Error:请输入white|black|phote_w|(220,220,220,0)RGBA形式')
    54. exit(1)
    55. return var
    56. if __name__ == "__main__":
    57. # change_png()
    58. t = Transcolor()
    59. photo_dir = 'imgs'
    60. for i in os.listdir(photo_dir):
    61. if os.path.splitext(i)[1].lower() in ['.jpg', '.png', '.jpeg', '.bmp']:
    62. path = os.path.join(photo_dir, i)
    63. t.transparent(path).save(path)
    64. print("完成")

    PIL检测图片是否包含透明通道

    • 执行的结果为True,说明我们经过透明化处理的图片是包含透明通道。
    1. from PIL import Image
    2. '''PIL检测图片是否包含透明通道'''
    3. def has_transparency(img):
    4. if img.mode == "P":
    5. transparent = img.info.get("transparency", -1)
    6. for _, index in img.getcolors():
    7. if index == transparent:
    8. return True
    9. elif img.mode == "RGBA":
    10. extrema = img.getextrema()
    11. if extrema[3][0] < 255:
    12. return True
    13. return False
    14. if __name__ == "__main__":
    15. # extract_alpha("./13.png")
    16. image = Image.open("output/input_output.png")
    17. print(has_transparency(image))

     可以看到执行的结果为True,说明我们经过透明化处理的图片是包含透明通道。

  • 相关阅读:
    Blazor 组件库 BootstrapBlazor 中Editor组件介绍
    SQL命令及MariaDB(二)
    智慧排水监测系统:实时监测城市排水情况
    空间金字塔池化Spatial Pyramid Pooling
    【C++】运算符的重载
    UE4切换关卡
    Asp .Net Core 系列:集成 Ocelot+Nacos+Swagger+Cors实现网关、服务注册、服务发现
    web课程设计网页规划与设计:HTML+CSS美妆设计题材——雅诗兰黛(5页)
    “华为杯”研究生数学建模竞赛2015年-【华为杯】B题:数据的多流形结构分析(附python代码实现)
    Win10一键重装系统后计算机图标怎么调出来
  • 原文地址:https://blog.csdn.net/qq_45956730/article/details/125596129