How to remove an image's background and make it transparent? - python

The code I use is this:
from PIL import Image
import os
path = 'C:/Users/User/Desktop/GF_BSIF/temp'
newData = []
for image in os.listdir(path):
img = Image.open(path+'/'+image)
img = img.convert("RGBA")
datas = img.getdata()
for item in datas:
if item[0] == 255 and item[1] == 255 and item[2] == 255:
newData.append((255, 255, 255, 0))
else:
if item[0] > 150:
newData.append((0, 0, 0, 255))
else:
newData.append(item)
print(item)
img.putdata(newData)
img.save('C:/Users/User/Desktop/GF_BSIF/temp'+'/'+"open_science_logo_transparent.png", "PNG")
Original:
Result:
The result does not exactly make the background transparent.
How to improve the code and make the black background into transparent?
EDIT:
from PIL import Image
import matplotlib.pyplot as plt
import os
import shutil
path = 'C:/Users/User/Desktop/GF_BSIF/temp'
out_put = 'C:/Users/User/Desktop/data science/cropped'
newData = []
for image in os.listdir(path):
img = Image.open(path+'/'+image)
img = img.convert("RGBA")
datas = img.getdata()
for item in datas:
if all(i == 0 for i in datas[0:3]):
newData.append((0, 0, 0, 0))
else:
etcetcetc
img.putdata(newData)
img.save('C:/Users/User/Desktop/GF_BSIF/temp'+'/'+"open_science_logo_transparent.png", "PNG")
#NotActuallyErik
It shows an error
TypeError Traceback (most recent call last)
in 14 15 for item in datas: ---> 16 if all(i == 0 for i in datas[0:3]): 17 newData.append((0, 0, 0, 0)) 18 else:
TypeError: sequence index must be integer, not 'slice'.
How to make it right?

Your code is telling PIL to remove replace every white pixel with a black one: [255,255,255,0] -> [0,0,0,255] which is why your black background remains while only the full-white spots get removed. You need to do the opposite to remove the background, i.e [0,0,0,255] -> [0,0,0,0]
this might work
for item in datas:
if all(i == 0 for i in datas[0:3]):
newData.append((0, 0, 0, 0))
else:
etcetcetc

Related

Using opencv to mask the background

I'm trying to use tesseract to read text from a game with poor results.
What I would like to accomplish is to remove the background from the image so that only the text is visible to improve OCR results.
I've tried cv2.inRange, thresholding yet I can't seem to get it to work.
import numpy as np
import pytesseract
from tesserocr import PyTessBaseAPI, OEM
def _img_to_bytes(image: np.ndarray, colorspace: str = 'LAB'):
# Sets an OpenCV-style image for recognition: https://github.com/sirfz/tesserocr/issues/198
bytes_per_pixel = image.shape[2] if len(image.shape) == 3 else 1
height, width = image.shape[:2]
bytes_per_line = bytes_per_pixel * width
if bytes_per_pixel != 1 and colorspace != 'RGB':
# non-RGB color image -> convert to RGB
image = cv2.cvtColor(image, getattr(cv2, f'COLOR_{colorspace}2RGB'))
elif bytes_per_pixel == 1 and image.dtype == bool:
# binary image -> convert to bitstream
image = np.packbits(image, axis=1)
bytes_per_line = image.shape[1]
width = bytes_per_line * 8
bytes_per_pixel = 0
# else image already RGB or grayscale
return image.tobytes(), width, height, bytes_per_pixel, bytes_per_line
img = cv2.imread("ref.png")
img = ~img
clahe = cv2.createCLAHE(clipLimit=3., tileGridSize=(8,8))
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)
l2 = clahe.apply(l)
lab = cv2.merge((l2,a,b))
img = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
with PyTessBaseAPI(psm=3, oem=OEM.LSTM_ONLY, path=f"ocr", lang=d2r ) as api:
api.ReadConfigFile("ocr/config.txt")
api.SetVariable("user_words_file","ocr/dict.txt")
api.SetImageBytes(*_img_to_bytes(img))
print(api.GetUTF8Text())
cv2.imshow('res',img)
cv2.waitKey()```
Inverting color may help? try this & let me know.
import cv2
image = cv2.imread("Bytelock.jpg")
image = ~image
cv2.imwrite("Bytelock.jpg",image)
Inverted image
Red varient
import numpy as np
import imutils
import cv2
img_rgb = cv2.imread('ss.jpg')
Conv_hsv_Gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(Conv_hsv_Gray, 0, 255,cv2.THRESH_BINARY_INV |cv2.THRESH_OTSU)
img_rgb[mask == 255] = [0, 0, 255]
cv2.imshow("red", img_rgb)
cv2.imwrite("red.jpg", img_rgb)
More sharpen? Try
import numpy as np
import imutils
import cv2
img_rgb = cv2.imread('ss.jpg')
Conv_hsv_Gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(Conv_hsv_Gray, 0, 255,cv2.THRESH_BINARY_INV |cv2.THRESH_OTSU)
img_rgb[mask == 255] = [0, 0, 255]
cv2.imwrite("mask.jpg", mask)
cv2.imshow("mask", mask) # show windows
cv2.waitKey(0)
**
Much more better option
**
import cv2
image = cv2.imread("ss1.jpg")
image = ~image
img = image
clahe = cv2.createCLAHE(clipLimit=3., tileGridSize=(8,8))
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)
l2 = clahe.apply(l)
lab = cv2.merge((l2,a,b))
img2 = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
cv2.imshow('Increased contrast', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
More sharpen

OpenCV Color Detection in video ROI

I am trying to figure out color in a specific ROI in Traffic Light Video. The code although predicts the color correctly it doesn't do it for the specific ROI i am looking at.
Initially when the traffic video starts the ROI region has no (RGY) colors but it still predicts and shows RED based on other areas. What am i doing wrong.
Have uploaded the test Video here for testing -- https://ufile.io/ha20buns
Python Code below.
import cv2
import numpy as np
cap = cv2.VideoCapture('D:\Videos\Sample.mp4')
while True:
ret,frame = cap.read()
if ret == False:
break
frame = cv2.resize(frame,(1920 ,1080))
#Extract required section from entire frame
roiColor = cv2.rectangle(frame.copy(),(1022, 565),(1411, 709),(255,255,255),2) #For SampleTL.mp4
blcolor = (255, 0, 0)
cv2.rectangle(frame, (1022, 565),(1411, 709), blcolor)
hsv = cv2.cvtColor(roiColor,cv2.COLOR_BGR2HSV)
#red
lower_hsv_red = np.array([157,177,122])
upper_hsv_red = np.array([179,255,255])
mask_red = cv2.inRange(hsv,lowerb=lower_hsv_red,upperb=upper_hsv_red)
red_blur = cv2.medianBlur(mask_red, 7)
#green
lower_hsv_green = np.array([49,79,137])
upper_hsv_green = np.array([90,255,255])
mask_green = cv2.inRange(hsv,lowerb=lower_hsv_green,upperb=upper_hsv_green)
green_blur = cv2.medianBlur(mask_green, 7)
lower_hsv_yellow = np.array([15,150,150])
upper_hsv_yellow = np.array([35,255,255])
mask_yellow = cv2.inRange(hsv,lowerb=lower_hsv_yellow,upperb=upper_hsv_yellow)
yellow_blur = cv2.medianBlur(mask_yellow, 7)
#Because the image is a binary image, If the image has a white point, which is 255, then take his maximum max value 255
red_color = np.max(red_blur)
green_color = np.max(green_blur)
yellow_color = np.max(yellow_blur)
if red_color == 255:
print('red')
cv2.rectangle(frame,(1020,50),(1060,90),(0,0,255),2 ) #Draw a rectangular frame by coordinates
cv2.putText(frame, "red", (1020, 40), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255),2) #red text information
elif green_color == 255:
print('green')
cv2.rectangle(frame,(1020,50),(1060,90),(0,255 ,0),2)
cv2.putText(frame, "green", (1020, 40), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0),2)
elif yellow_color == 255:
print('yellow')
cv2.rectangle(frame,(1020,50),(1060,90),(0,255 ,0),2)
cv2.putText(frame, "yellow", (1020, 40), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 255, 0),2)
cv2.imshow('frame',frame)
red_blur = cv2.resize(red_blur,(300,200))
green_blur = cv2.resize(green_blur,(300,200))
yellow_blur = cv2.resize(yellow_blur, (300,200))
#cv2.imshow('red_window',red_blur)
#cv2.imshow('green_window',green_blur)
#cv2.imshow('yellow_window',yellow_blur)
c = cv2.waitKey(10)
if c==27:
break
cap.release()
cv2.destroyAllWindows() # destroy all opened windows
cv2.rectangle doesn't crop the image but returns the original image with a drawn rectangle. Try this instead:
roiColor = frame[565:709, 1022:1411]

How to remove the clickable transparent background from an image using python or python library?

Default Image(befor cropping)
***How to convert this image to the cropped image ***
Image after cropping
You can use pillow module in python to create transparent background.
from PIL import Image
def convertImage():
img = Image.open("7OUBR.png")
img = img.convert("RGBA")
datas = img.getdata()
newData = []
for item in datas:
if item[0] == 255 and item[1] == 255 and item[2] == 255:
newData.append((255, 255, 255, 0))
else:
newData.append(item)
img.putdata(newData)
img.save("glass.png", format="png")
print("Successful")
convertImage()

PIL image rotation and background issue

I am trying to rotate my transparent gif using the PIL rotate() but I am getting a diamond after rotating it.
Similar problems on SO were solved by using
transparency = img.info['transparency']
img.save('result.gif',transparency=transparency)
or by using
img.save('result.gif', **img.info)
But I am getting the following results as in the images.
My code is
from PIL import Image
file = 'change2_1.gif'
with Image.open(file) as im:
transparency = im.info['transparency']
img = im.rotate(45, expand=True)
img.save('result.gif', transparency=transparency)
Post edited: Try to use this to make black backgroud transparent
from PIL import Image
img = Image.open('img.png')
img = img.convert("RGBA")
datas = img.getdata()
with Image.open(file) as im:
transparency = im.info['transparency']
img = im.rotate(90, expand=True)
img.save('result.gif', transparency=transparency)
newData = []
for item in datas:
if item[0] == 0 and item[1] == 0 and item[2] == 0:
newData.append((255, 255, 255, 0))
else:
newData.append(item)
To avoid having a black frame after rotation, simply change the default mode ('RGB') to 'RGBA' after opening :
img = Image.open('image.png').convert('RGBA')
img.rotate(90, expand = True)

Python PIL image transparent issue

I am trying to make an image transparent.
This is my image
from PIL import Image
img = Image.open('Frame 0001.png')
img = img.convert("RGBA")
datas = img.getdata()
newData = []
for item in datas:
if item[0] == 255 and item[1] == 255 and item[2] == 255:
newData.append((255, 255, 255, 0))
else:
newData.append(item)
img.putdata(newData)
img.save("img2.png", "PNG")
My output image is this:
Well Googled a bit and found a package called cv2. Had a tough time installing that package, but the thing I was trying to do was possible
import cv2
img1=cv2.imread('m1.jpg')
img2=cv2.imread('logo.jpg')
dst=cv2.addWeighted(img1,0.7,img2,0.3,0)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

Categories