python: want to display red channel only in opencv - python

I am beginner in image processing. I am showing image in many color space the below code show the image in the 3 channels R G B however the image displayed in the gray layout. i need to display three images one with red channel as red image, another as blue, and the last one as green. thanks in advance.
# cspace.py
import cv2
import numpy as np
image = cv2.imread('download.jpg')
# Convert BGR to HSV
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
hsl = cv2.cvtColor(image, cv2.COLOR_BGR2HLS) # equal to HSL
luv = cv2.cvtColor(image, cv2.COLOR_BGR2LUV)
#RGB - Blue
cv2.imshow('B-RGB.jpg',image[:, :, 0])
cv2.imwrite('B-RGB.jpg',image[:, :, 0])
# RGB - Green
cv2.imshow('G-RGB',image[:, :, 1])
cv2.imwrite('G-RGB.jpg',image[:, :, 1])
# RGB Red
cv2.imshow('R-RGB',image[:, :, 2])
cv2.imwrite('R-RGB.jpg',image[:, :, 2])
cv2.waitKey(0)
Blue image as displayed currently
i need to display blue channel like this image

You can just make a copy of the original image and set some channels to 0.
import cv2
image = cv2.imread('download.jpg')
b = image.copy()
# set green and red channels to 0
b[:, :, 1] = 0
b[:, :, 2] = 0
g = image.copy()
# set blue and red channels to 0
g[:, :, 0] = 0
g[:, :, 2] = 0
r = image.copy()
# set blue and green channels to 0
r[:, :, 0] = 0
r[:, :, 1] = 0
# RGB - Blue
cv2.imshow('B-RGB', b)
# RGB - Green
cv2.imshow('G-RGB', g)
# RGB - Red
cv2.imshow('R-RGB', r)
cv2.waitKey(0)

import cv2
import numpy as np
channel_initials = list('BGR')
image = cv2.imread('download.jpg')
for channel_index in range(3):
channel = np.zeros(shape=image.shape, dtype=np.uint8)
channel[:,:,channel_index] = image[:,:,channel_index]
cv2.imshow(f'{channel_initials[channel_index]}-RGB', channel)
cv2.waitKey(0)

Related

Get transparent background by using mask, I get white background

def combined_display(image, matte):
# calculate display resolution
w, h = image.width, image.height
rw, rh = 800, int(h * 800 / (3 * w))
# obtain predicted foreground
image = np.asarray(image)
if len(image.shape) == 2:
image = image[:, :, None]
if image.shape[2] == 1:
image = np.repeat(image, 3, axis=2)
elif image.shape[2] == 4:
image = image[:, :, 0:3]
matte = np.repeat(np.asarray(matte)[:, :, None], 3, axis=2) / 255
foreground = image * matte + np.full(image.shape, 255) * (1 - matte)
foreground = Image.fromarray(np.uint8(foreground))
foreground.save("imag.png", format="png")
return foreground
I'm trying to get transparent background like removebg, I don't want white background. Please help me with removing background and get transparent background.
Suppose you have a 3-channel image and a 1-channel mask. Then you can stack them together into a 4-channel image where the last channel is responsible for transparency.
import numpy as np
from PIL import Image
image = Image.open('image.png')
mask = Image.open('mask.png').convert('L')
image_with_transparency = np.dstack((image, mask))
Image.fromarray(image_with_transparency).save('image_trs.png')
The result:

How to change the set of pixel colors in contatc with black color

Considering this image:
I would like to change the set of white pixels in contact with black pixels by red, this way:
I tried to use this code in python:
import numpy as np
from PIL import Image
im = Image.open('image.png')
data = np.array(im)
r1, g1, b1 = 255, 255, 255 # Original value
r2, g2, b2 = 0, 0, 255 # Value that we want to replace it with
red, green, blue = data[:,:,0], data[:,:,1], data[:,:,2]
mask = (red == r1) & (green == g1) & (blue == b1)
data[:,:,:3][mask] = [r2, g2, b2]
im = Image.fromarray(data)
But I changed all white pixels by red. But could be an UNIX approach suggestion too.
Please, post lossless versions of your input images. Lossy images modify the value of the pixels, creating artifacts that affect processing. I recreated your image and saved it as a lossless PNF file.
I'm using OpenCV to get the result you want. I created a mask with the non-zero elements of your original input. Then, I used Flood-fill to fill the outer shapes with the color you want. The final image can be obtained if you AND both images.
Let's see the code:
# import opencv:
import cv2
# image path
path = "D://opencvImages//"
fileName = "rectsLossless.png"
# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Grayscale image:
grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
# Get non-zero mask:
binaryThresh = 1
_, binaryMask = cv2.threshold(grayscaleImage, binaryThresh, 255, cv2.THRESH_BINARY)
This bit creates the non-zero pixels mask:
This will help to zero all the elements that are non-white. That image is the first part of the mask. Now, let's fill the outer shapes with red color. This is achieved in three steps:
# Get image dimensions:
(imageHeight, imageWidth) = inputImage.shape[:2]
# Get image center:
xCenter = int(0.5 * imageWidth)
yCenter = int(0.5 * imageHeight)
# Get flood-fill target color
floodColor = inputImage[yCenter, xCenter]
print("Flood Color: %s" % floodColor)
# numpy array to tuple
floodColor = (int(floodColor[0]), int(floodColor[1]), int(floodColor[2]))
The first step gets the actual filling color. I suppose that the red is located more or less at the center of the image. Then, the second step involves filling all the "foreground" pixels with white. Let's seed at the top left corner:
# Flood fill at top left corner:
leftCorner = (1, 1)
whiteColor = (255, 255, 255)
cv2.floodFill(inputImage, None, leftCorner, whiteColor)
This is the result:
Note how the shapes that are partially outside of the red rectangle are all now connected by the white color. Let's fill again, but this time using the red color I extracted previously:
# Second Flood-fill
cv2.floodFill(inputImage, None, leftCorner, floodColor)
This yields the following image:
Let's create the final image by ANDing this result with the original non-zero mask:
# Create final image:
outImage = cv2.bitwise_and(inputImage, inputImage, mask=binaryMask)
This is the final result:
The question is very close to this question.
My solution is close too...
Assuming the colors are black white and red (the general case may be trickier), we may use the following stages:
Fill the black background with white color (using cv2.floodFill).
The white object on the red boundary are merged with the background.
Fill the white background with black color (using cv2.floodFill).
The white object on the red boundary are going to be black.
Copy the red color channel from the original image to "filled" image.
The red channel of a white pixel is 255, so black and white becomes red.
Code sample:
import cv2
import numpy as np
img = cv2.imread('red_white_black.jpg')
# Copy the original image to img2
img2 = img.copy()
# Fill the black background with white color
cv2.floodFill(img2, None, seedPoint=(0, 0), newVal=(255, 255, 255), loDiff=(50, 50, 50), upDiff=(50, 50, 50))
cv2.imshow('black background', img2) # Show img2 for testing
# Fill the white background with black color
cv2.floodFill(img2, None, seedPoint=(0, 0), newVal=(0, 0, 0), loDiff=(50, 50, 50), upDiff=(50, 50, 50))
cv2.imshow('white background', img2) # Show img2 for testing
# Copy the red color channel from the original image to img2
img2[:, :, 2] = img[:, :, 2]
cv2.imshow('img2', img2) # Show img2 for testing
cv2.waitKey()
cv2.destroyAllWindows()
Results:
Black background:
White background:
img2:
The black margins around the red, are because the original image is JPEG and not PNG (colors are not pure), and the red is not pure red.
We may fix it using the following code (the code in not very elegant)...
red = img[:, :, 2]
r = np.median(img[:, :, 2][red > 50])
g = np.median(img[:, :, 1][red > 50])
b = np.median(img[:, :, 0][red > 50])
mask = np.logical_and(img[:, :, 0] > 100, img2[:, :, 0] <= 100)
img3 = img2.copy()
img3[:, :, 2][mask] = r
img3[:, :, 1][mask] = g
img3[:, :, 0][mask] = b
img3[:, :, 2] = cv2.morphologyEx(img3[:, :, 2], cv2.MORPH_CLOSE, np.ones((3, 3), np.uint8))
img3[:, :, 1] = cv2.morphologyEx(img3[:, :, 1], cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
img3[:, :, 0] = cv2.morphologyEx(img3[:, :, 0], cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
cv2.imshow('img3', img3)
cv2.waitKey()
cv2.destroyAllWindows()
Result:

How to remove visible background boundary around object after saliency detection?

I am working on a background removal problem. I used Deep learning based saliency detection technique to separate foreground and background.
Sample Input - https://imgur.com/8v0wet0
Result after Background Removal - https://imgur.com/eXu6Hmo
As you can see there is a bluish hue around the footballer. Is there any image processing technique to remove this?
What I tried?
I have already tried eroding mask (alpha channel) using cv.erode but did not get good results.
Here is one way in Python/OpenCV by desaturating blue, eroding, masking and anti-aliasing.
- Read input unchanged to keep the alpha channel
- Extract the BGR channels
- Extract the Alpha channel
- Erode the alpha channel
- Create the outline mask where the blue remains
- Create a blue mask showing where the image is blue
- Create the logical and of the two masks
- Desaturate the BGR image
- Blend the BGR with the desaturated image using the mask
- Blur the alpha channel
- Stretch mid-gray or higher to black to antialias the blurred alpha channel
- Put the antialiased alpha channel into the blended BGR image
- Save the results
Input:
import cv2
import numpy as np
import skimage.exposure
# load image with alpha channel
img = cv2.imread('bg_removed.png', cv2.IMREAD_UNCHANGED)
# extract only bgr channels
bgr = img[:, :, 0:3]
# extract alpha channel
a = img[:, :, 3]
# erode alpha channel
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
ae = cv2.morphologyEx(a, cv2.MORPH_ERODE, kernel)
# compute outline mask as difference
omask = a - ae
omask[omask>0] = 255
# create blue mask
lower=(135,100,0)
upper=(185,160,150)
bmask = cv2.inRange(bgr, lower, upper)
# mask as product of omask and bmask
mask = cv2.bitwise_and(omask, bmask)
imask = 255 - mask
# create desaturated bgr image
hsv = cv2.cvtColor(bgr, cv2.COLOR_BGR2HSV)
hsv[:,:,1] = 0
bgrd = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
# blend bgr, bgrd using mask
bgr_imask = cv2.bitwise_and(bgr, bgr, mask=imask)
bgrd_mask = cv2.bitwise_and(bgrd, bgrd, mask=mask)
bgr_new = cv2.add(bgr_imask, bgrd_mask)
# blur alpha channel
ab = cv2.GaussianBlur(ae, (0,0), sigmaX=3, sigmaY=3, borderType = cv2.BORDER_DEFAULT)
# stretch values to 0
aa = skimage.exposure.rescale_intensity(ab, in_range=(200,255), out_range=(0,255))
# replace alpha channel in bgr_new with new alpha channel
out = bgr_new.copy()
out = cv2.cvtColor(out, cv2.COLOR_BGR2BGRA)
out[:, :, 3] = aa
# save output
cv2.imwrite('bg_removed_antialias.png', out)
# Display various images to see the steps
cv2.imshow('BGR', bgr)
cv2.imshow('Alpha', a)
cv2.imshow('AE', ae)
cv2.imshow('AB', ab)
cv2.imshow('AA', aa)
cv2.imshow('Outline Mask', omask)
cv2.imshow('Blue Mask', bmask)
cv2.imshow('MASK', mask)
cv2.imshow('IMASK', imask)
cv2.imshow('BGR_IMASK', bgr_imask)
cv2.imshow('BGRD_MASK', bgrd_mask)
cv2.imshow('BGR_NEW', bgr_new)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result:

OpenCV overlay 2 image based on image mask

I need overlay 2 images based on third image mask
Example
1.-I have this background
2.-I have this object image and also i have de segmentation image
Object image
I'm try to merge Backgound and Object image based on third image (mask image)
(mask image)
The final result is Background image + Object image(only based on mask)
Any idea..
I tried
import cv2
added_image = cv2.addWeighted(back_img,0.4,aug_demoimage,0.1,0)
But not working as expected.. any sugestion? thanks!
Solved
def get_only_object(img, mask, back_img):
fg = cv2.bitwise_or(img, img, mask=mask)
#imshow(fg)
# invert mask
mask_inv = cv2.bitwise_not(mask)
#fg_back = cv2.bitwise_or(back_img, back_img, mask=mask)
fg_back_inv = cv2.bitwise_or(back_img, back_img, mask=mask_inv)
#imshow(fg_back_inv)
final = cv2.bitwise_or(fg, fg_back_inv)
#imshow(final)
return final
You need to convert the object image into an RGBA image where the alpha channel is the mask image you have created. Once you do this, you can paste it to the background image.
def convert_to_png(img, a):
#alpha and img must have the same dimenstons
fin_img = cv2.cvtColor(img, cv2.COLOR_RGB2RGBA)
b, g, r, alpha = cv2.split(fin_img)
alpha = a
# plt.imshow(alpha);plt.title('alpha image');plt.show()
# plt.imshow(img);plt.title('original image');plt.show()
# plt.imshow(alpha);plt.title('fin alpha image');plt.show()
fin_img[:,:, 0] = img[:,:,0]
fin_img[:,:, 1] = img[:,:,1]
fin_img[:,:, 2] = img[:,:,2]
fin_img[:,:, 3] = alpha[:,:]
# plt.imshow(fin_img);plt.title('fin image');plt.show()
return fin_img
This function will combine the two images into an RGBA image.
y1, y2 = new_loc[1], new_loc[1] + img.shape[0]
x1, x2 = new_loc[0], new_loc[0] + img.shape[1]
alpha_s = img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s
for c in range(0, 3):
fin_img[y1:y2, x1:x2, c] = (alpha_s * img[:, :, c] +
alpha_l * img[y1:y2, x1:x2, c])
And this will copy the Object image to the background image

How to substract "hue" of an image from the original image using OPENCV

I am trying to subtract the "hue" part of an image from that image.I have extracted all the h,s,v components .But i do not know what to do next?Is it even possible??
Here is my code
import cv2
def showimage(text,img):
cv2.imshow(text,cv2.resize(img, (700, 700)))
cv2.waitKey(0)
return 0
# Read image in BGR
img_path = "new.jpg"
img = cv2.imread(img_path)
showimage("orig",img)
# Convert BGR to HSV and parse HSV
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
showimage("hsv",hsv_img)
h, s, v = hsv_img[:, :, 0], hsv_img[:, :, 1], hsv_img[:, :, 2]
showimage("h",h)
showimage("s",s)
showimage("v",v)
sub=hsv_img-h
cv2.destroyAllWindows()
You cant subtract hsv_img and h as they are of not same dimensions. However, you can subtract a grayscale version of the image with h. For that, add the lines -
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sub = gray_img-h
showimage("sub",sub)
However, if you are trying to visualize an image with zero hue component, you can do that with the code below -
Example:
import cv2
import numpy as np
def showimage(text,img):
cv2.imshow(text,cv2.resize(img, (500,500)))
cv2.waitKey(0)
return 0
# Read image in BGR
img_path = "new.jpg"
img = cv2.imread(img_path)
showimage("orig",img)
# Convert BGR to HSV and parse HSV
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
showimage("hsv",hsv_img)
h, s, v = hsv_img[:, :, 0], hsv_img[:, :, 1], hsv_img[:, :, 2]
showimage("h",h)
showimage("s",s)
showimage("v",v)
h = np.zeros_like(h)
img2 = cv2.merge((h,s,v))
img2 = cv2.cvtColor(img2, cv2.COLOR_HSV2BGR)
showimage("With h=0 ", img2)
cv2.destroyAllWindows()

Categories