如何在 Python 中删除部分 PNG 图像以使其不透明

问题描述

我有一个在 PNG 图像上创建遮挡的脚本。来自https://arxiv.org/pdf/2001.04086.pdf的数据增强遮挡技术。

脚本在创建遮挡方面运行良好,但它们在 PNG 上绘制为黑色矩形。

我希望他们做的是从 PNG 中切出这些矩形,并使它们成为 PNG 的 alpha 层的一部分,这样当粘贴到背景上时,背景就会通过矩形显示出来。基本上使黑色矩形透明。

当前的实现输出如下所示:

enter image description here

完整的脚本如下,但需要在这里工作的区域:

    # Draw each Box onto the image
    for index,row in Boxes.iterrows():
        shape = [(row['topleftcornerxpx'],row['topleftcornerypx']),(row['topleftcornerxpx'] + row['sizepx'],row['topleftcornerypx'] + row['sizepx'])]
        img1 = ImageDraw.Draw(img)
        img1.rectangle(shape,fill = "black")

已尝试添加 alpha 蒙版,但这会从背景中移除 alpha 通道并使矩形保持黑色。

    # Draw each Box onto the image
    for index,row['topleftcornerypx'] + row['sizepx'])]
        mask = Image.new('L',img.size,color = 255)
        draw=ImageDraw.Draw(mask)
        img1 = ImageDraw.Draw(img)
        img1.rectangle(shape,fill=0)
        img.putalpha(mask)

完整的脚本(有人可能会喜欢):

import os
from pandas import DataFrame
from PIL import Image,ImageDraw
import numpy as np

#set directories
directory = str("C:/GIT/Temp/Test/test/")
target_directory = str("C:/GIT/Temp/Test/test/occluded/")
occlusion_scales = [.20,.125,.08] #Percent of image the occlusions will cover. Add or remove as many as required.  
image_padding = int(5)

existing_files = os.listdir(target_directory)
#print(existing_files)

#Get files
for filename in os.listdir(directory):
  if filename.endswith('.png'):
      # Process for each occlusion scale in the list. 
      for scales in occlusion_scales:
        img = Image.open(directory + filename)
        # Get image dimensions
        imgwidth,imgheight = img.size
        # Get smallest value out of x & y to scale Box size by. 
        Box1sizepx = round(min(imgwidth,imgheight) * scales)
        print(filename)
        
        #Dont process files already processed,can comment out for replace. 
        if (filename.replace('.png','') + '_occluded_' + str(scales)+'.png') not in existing_files: 
            #print(filename + ' not in list')
            
            # Calculate number of Boxes accross and down required
            Boxesaccross = round((imgwidth/2) / Box1sizepx)
            Boxesdown = round((imgheight/2) / Box1sizepx)

            # Create dataframe for Boxes 
            Boxes = DataFrame(columns=['sizepx','topleftcornerxpx','topleftcornerypx'])
            # Set row counter for loop.
            Boxrow = 0

            #Draw a Box for each row and within that each column
            while Boxesdown >= 1:
                Boxesdown = Boxesdown -1
                Boxcolumn = 0

                while Boxesaccross >= 1: 
                    Boxesaccross = Boxesaccross -1
                    new_Box = {'sizepx':Box1sizepx,'topleftcornerxpx':round(Box1sizepx*.8) + (Box1sizepx * Boxcolumn),'topleftcornerypx':round(Box1sizepx*.8) + (Box1sizepx * Boxrow)}
                    Boxes = Boxes.append(new_Box,ignore_index=True)
                    Boxcolumn = Boxcolumn + 2

                Boxrow = Boxrow + 2
                Boxesaccross = round((imgwidth/2) / Box1sizepx)

            # Draw each Box onto the image
            for index,row in Boxes.iterrows():
                shape = [(row['topleftcornerxpx'],row['topleftcornerypx'] + row['sizepx'])]
                img1 = ImageDraw.Draw(img)
                img1.rectangle(shape,fill = "black")

            #Save the image 
            print(target_directory + filename.replace('.png','') + '_occluded_' + str(scales)+'.png')

            #Crop the image with some padding
            cropped_object = img.crop(((0 - image_padding),(0 - image_padding),(imgwidth + image_padding),(imgheight + image_padding)))
            cropped_object.save(target_directory + filename.replace('.png','') + '_occluded_' + str(scales)+'.png')

解决方法

解决了感谢@furas,将填充设置为0而不是“黑色”。如果有人想要的话,更新了脚本。

import os
from pandas import DataFrame
from PIL import Image,ImageDraw
import numpy as np

#set directories
directory = str("C:/GIT/Temp/Test/test/")
target_directory = str("C:/GIT/Temp/Test/test/occluded/")
occlusion_scales = [.20,.125,.08] #Percent of image the occlusions will cover. Add or remove as many as required.  
image_padding = int(5)

existing_files = os.listdir(target_directory)
#print(existing_files)

#Get files
for filename in os.listdir(directory):
  if filename.endswith('.png'):
      # Process for each occlusion scale in the list. 
      #pixdata = filename.load()
      #print(pixdata)
      for scales in occlusion_scales:
        img = Image.open(directory + filename)
        # Get image dimensions
        imgwidth,imgheight = img.size
        # Get smallest value out of x & y to scale box size by. 
        box1sizepx = round(min(imgwidth,imgheight) * scales)
        print(filename)
        
        #Dont process files already processed,can comment out for replace. 
        if (filename.replace('.png','') + '_occluded_' + str(scales)+'.png') not in existing_files: 
            #print(filename + ' not in list')
            
            # Calculate number of boxes accross and down required
            boxesaccross = round((imgwidth/2) / box1sizepx)
            boxesdown = round((imgheight/2) / box1sizepx)

            # Create dataframe for boxes 
            boxes = DataFrame(columns=['sizepx','topleftcornerxpx','topleftcornerypx'])
            # Set row counter for loop.
            boxrow = 0

            #Draw a box for each row and within that each column
            while boxesdown >= 1:
                boxesdown = boxesdown -1
                boxcolumn = 0

                while boxesaccross >= 1: 
                    boxesaccross = boxesaccross -1
                    new_box = {'sizepx':box1sizepx,'topleftcornerxpx':round(box1sizepx*.8) + (box1sizepx * boxcolumn),'topleftcornerypx':round(box1sizepx*.8) + (box1sizepx * boxrow)}
                    boxes = boxes.append(new_box,ignore_index=True)
                    boxcolumn = boxcolumn + 2

                boxrow = boxrow + 2
                boxesaccross = round((imgwidth/2) / box1sizepx)

            # Draw each box onto the image
            for index,row in boxes.iterrows():
                shape = [(row['topleftcornerxpx'],row['topleftcornerypx']),(row['topleftcornerxpx'] + row['sizepx'],row['topleftcornerypx'] + row['sizepx'])]
                img1 = ImageDraw.Draw(img)
                img1.rectangle(shape,fill = 0)

            #Save the image 
            print(target_directory + filename.replace('.png','') + '_occluded_' + str(scales)+'.png')

            #Crop the image with some padding
            cropped_object = img.crop(((0 - image_padding),(0 - image_padding),(imgwidth + image_padding),(imgheight + image_padding)))
            cropped_object.save(target_directory + filename.replace('.png','') + '_occluded_' + str(scales)+'.png')

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...