I am new to OpenCV so please bear with me if my qustion seems silly to you.
I have a set of images that all have a transparent border on the left and right like you can see below:
I want to erase these borders so I thought about edge detection which would be easy to do if I could transform these transparent borders to a white color. In the Docs I found that you can do this:
img = cv2.imread("./Green/image-000.png", 1)
cv2.imwrite('../image-000.png', img)
This erases the alpha channel of the png image but turns it into black.
Is there something similar that turns the borders white?
Or is there even a simpler method of erasing these borders?
You would make me really happy if you could help me!
PS: I use Python 2.7 and OpenCV 3.4
You should load image with IMREAD_UNCHANGED, i.e.
import cv2 as cv
img = cv.imread("./Green/imgage-000.png", cv.IMREAD_UNCHANGED)
Then, your image will have 4 channels (BGRA), and you can use alpha channel mask to turn the corresponding part to white:
alpha_channel = img[:, :, 3]
_, mask = cv.threshold(alpha_channel, 254, 255, cv.THRESH_BINARY) # binarize mask
color = img[:, :, :3]
new_img = cv.bitwise_not(cv.bitwise_not(color, mask=mask))
I tested this code with a transparent PNG where the color channels were black and the information was in the transparency:
The nested bitwise_not is ugly but is the only way I found to make it work.
Related
I'm looking for a way to recreate the GIMP's Erase color blending mode in Python 3 & OpenCV2.
I know it's possible to erase color using the that library, but the code I run works on exactly one of them. Furthermore, I don't believe such small amount of code could do that advanced thing.
Looking for a solution, I found the blend-modes by flrs, but it also doesn't include the option I want.
Sadly, I have no experience in OpenCV2 at the moment, but I think developing such thing could be very helpful.
Can someone guide me how to make this more reliable, or is it even possible to do with things that I've got already?
OpenCV2 color removal
Code
import cv2
from PIL import Image
#-=-=-=-#
File_Name = r"Spectrogram.png"
SRC = cv2.imread(File_Name, 1)
TMP = cv2.cvtColor(SRC, cv2.COLOR_BGR2GRAY)
_, A = cv2.threshold(TMP, 0, 255, cv2.THRESH_BINARY)
B, G, R = cv2.split(SRC)
Colors = [B, G, R, A]
Picture = cv2.merge(Colors, 4)
#-=-=-=-#
# My CV2 image display doesn't include transparency
im = cv2.cvtColor(Picture, cv2.COLOR_BGR2RGB)
im = Image.fromarray(im)
im.show()
Result
Original
Result
GIMP Erase color blending-mode
Type
Background
Foreground
Result
Image
Blending
Normal
Erase color
Normal
Here is one simple way in Python/OpenCV.
Read the input
Choose a color range
Apply range to threshold the image
Invert the range as a mask to be used later for the alpha channel
Convert the image from BGR to BGRA
Put mask into the alpha channel of the BGRA image
Save the result
Input:
import cv2
import numpy as np
# load image and set the bounds
img = cv2.imread("red_black.png")
# choose color range
lower =(0,0,0) # lower bound for each BGR channel
upper = (140,0,190) # upper bound for each BRG channel
# create the mask
mask = cv2.inRange(img, lower, upper)
# invert mask
mask = 255 - mask
# convert image to BGRA
result = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
# put mask into alpha channel
result[:,:,3] = mask
# write result to disk
cv2.imwrite("red_black_color_removed.png", result)
# display it (though does not display transparency properly)
cv2.imshow("mask", mask)
cv2.imshow("results", result)
cv2.waitKey(0)
Result:
Hi I want to remove the white border from this Logo using python's pillow library. The only way I have thought of is to extract all white from the image but then this remove's the white eye of the horse as well and that is something I would like to keep.
What I have.
https://i.stack.imgur.com/DX2LE.png
What I want.
https://i.stack.imgur.com/IPVqi.png
This isn't a daunting task but there are a lot of logo's that I need to do this for so I would like an automated fashion of doing so. Here is some code to extract the image from the source. Thanks for any help anyone can provide.
from PIL import Image
import pandas as pd
import requests
filename = "https://a.espncdn.com/combiner/i?img=/i/teamlogos/ncaa/500/68.png"
image = Image.open(requests.get(filename, stream=True).raw)
I prefer using OpenCV but we can do it with PIL.
Replace white with transparency using the example from here
Get the alpha channel.
Use ImageDraw.floodfill for filling the surrounding zero alpha with 255 color.
(Only the eye stays black).
Invert alpha - make the eye white instead of black.
Paste the white eye on the image with the "transparent white".
Code sample (reading local image):
from PIL import Image, ImageDraw, ImageOps
import numpy as np
# https://stackoverflow.com/questions/765736/how-to-use-pil-to-make-all-white-pixels-transparent
def white_to_transparency(img):
x = np.asarray(img.convert('RGBA')).copy()
x[:, :, 3] &= (255 * (x[:, :, :3] != 255).any(axis=2)).astype(np.uint8) # Small modification: &= is used instead of = (in the original code).
return Image.fromarray(x)
filename = "68.png"
image = Image.open(filename)
im_white_transparent = white_to_transparency(image)
# https://stackoverflow.com/questions/63219166/advanced-cropping-with-python-imaging-library
# Extract alpha channel as new Image
alpha = im_white_transparent.getchannel('A')
# https://stackoverflow.com/questions/46083880/fill-in-a-hollow-shape-using-python-and-pillow-pil
# Fill alpha channel with 255, only the inner part stays 0
ImageDraw.floodfill(alpha, xy=(0, 0), value=255, thresh=200)
mask = ImageOps.invert(alpha) # Invert alpha - make the eye white instead of black
im_white_transparent.paste(image, (0, 0), mask) # Paste the white eye on the image with "transparent white".
# Show images for testing
im_white_transparent.show()
alpha.show()
mask.show()
Result:
im_white_transparent:
(change to dark mode for seeing the transparent background):
Same result with transparency as chessboard pattern:
mask:
I need help thresholding a picture. I need identify different types of gummies but i cannot get past the thresholding part of my project.
I have various pictures but this is one of them:
I have done this using mean_c threshold but i need better results to find the countours after.
This is the original picture:
You may get better results by converting the image from RGB to HSV color space and threshold by hue (that's color value) and saturation (that's how much color is there compared to the gray value). Using saturation you might get the most of your gummies, except the transparent ones -- these are quite hard to get.
On the other hand, you may try to use edge detections, since your paper is flat and gummies really stand out. Here's the edge detection result I've got:
here's the code:
#!/usr/bin/env python
import cv2
img = cv2.imread( 'Downloads/gummies.jpg' )
img = cv2.pyrDown(cv2.pyrDown( img ))
laplacian = cv2.Laplacian(img, cv2.CV_8U)
cv2.normalize( laplacian, img, 0, 600, cv2.NORM_MINMAX)
cv2.imshow( 'frame', img )
cv2.waitKey(0)
cv2.destroyAllWindows()
Example
I will try to explain my question according the image. Firstly i use Python3 and OpenCV3. I just want to colorize the white pixels of mask(for example with shinny blue). Then using addWeighted, i want to blend that mask onto original image. But the problem i can't colorize the mask. Mask is the result of inRange fuction and i can't transform it to RGB.
https://www.youtube.com/watch?v=hQ-bpfdWQh8
Just like in the video but single frame.
For a quick mask visualization, try this:
debug_img = img/2 + mask/2
If img isn't grayscale already, replace img with img.mean(axis=2) or use cvtColor().
Another way is to use indexing:
debug_img = img.copy()
debug_img[mask>0] = (0, 255, 0) # replace masked pixels with green
To make the green transparent, simply add
debug_img = debug_img/2 + img/2
I am trying to combine three images together. The image I want on the bottom is a 700x900 image with all black pixels. On top of that I want to paste an image that is 400x400 with an offset of 100,200. On top of that I want to paste an image border that is 700x900. The image border has alpha=0 in the inside of it and alpha=0 around it because it doesn't have straight edges. When I run the code I have pasted below I encounter 2 problems:
1) Everywhere on the border image where the alpha channel = 0, the alpha channel has been set to 255 and the color white shows instead of the black background and the image I am putting the border around.
2) The border image's quality has been significantly reduced and looks a lot different than it should.
Also: part of the border image will cover part of the Image I am putting the border around. So I can't just switch the order that I am pasting.
Thanks in advance for any help.
#!/usr/bin/python -tt
from PIL import ImageTk, Image
old_im2 = Image.open('backgroundImage1.jpg') # size = 400x400
old_im = Image.open('topImage.png') # size = 700x900
new_size = (700,900)
new_im = Image.new("RGBA", new_size) # makes the black image
new_im.paste(old_im2, (100, 200))
new_im.paste(old_im,(0,0))
new_im.show()
new_im.save('final.jpg')
I think you have a misconception about images - the border image does have pixels everywhere. It's not possible for it to be "missing" pixels. It is possible to have an image with an alpha channel, which is a channel like the R, G, and B channels, but indicates transparency.
Try this:
1. Make sure that topImage.png has a transparency channel, and that the pixels that you want to be "missing" are transparent (i.e. have a maximum alpha value). You can double check this way:
print old_im.mode # This should print "RGBA" if it has an alpha channel.
2. Create new_im in "RGBA" mode:
new_im = Image.new("RGBA", new_size) # makes the black image
# Note the "A" --------^
3. Try this paste statement instead:
new_im.paste(old_im,(0,0), mask=old_im) # Using old_im as the mask argument should tell the paste function to use old_im's alpha channel to combine the two images.