CV2 add 2 images without transparency Python - python

I'm working on an image processing project. I have 2 RGB images and I would like to create a new one by overlapping the 2 input images.
This is my 2 input images:
I'm using the cv2 "add" method to achieve this. But the result is not the hoped result...
The result is as follows:
I don't want to have a transparency on my red stripe. I would like something opaque, which covers the crack on the image 1.
There is my code:
img1 = cv2.imread(r"C:\Users\francois.bock\Desktop\crack.jpg")
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
img2 = cv2.imread(r"C:\Users\francois.bock\Desktop\line.png")
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)
# Adding two images
add = cv2.add(img1, img2)
#Display the image
img = PImage.fromarray(add)
img.show()
I also naively tried to add the 2 images like that:
add = img1 + img2
add = add.astype(np.uint8)
But the result is even stranger.
I also used the cv2 "addWeighted" method, but it also gives a transparent stripe.
So my question is, is there a simple way to add 2 images without transparency? Thank you in advance.

You can do it with straight Numpy:
import numpy as np
import cv2
a = cv2.imread('a.jpg')
b = cv2.imread('b.png')
# Make "a" red anywhere b>0
a[ np.any(b>0,axis=-1) ] = [0,0,255]
If you happen to have blue and green or any other colour lines lurking in your image too, you can use this:
# Anywhere image "b" is not black, use image "b", else use image "a"
result = np.where(np.any(b>0,axis=-1,keepdims=True), b, a)

Related

How to see if an image is contained in another image image and get an output of 1 if there is or 0 if there isn't?

I have a script that takes a screenshot of the screen and I want to see if a smaller image is within it. I'm currently using pyAutoGui to take the screenshot. I know that I can use open-cv but I don't know how to turn it into a boolean value, like when the smaller image is detected to give a 1 or like True and when it's not to give a 0 or False. Thank You!
You can use the cv2.matchTemplate method:
import cv2
import numpy as np
img1 = cv2.imread("image1.png")
img2 = cv2.imread("image2.png")
img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
res = cv2.matchTemplate(img1_gray, img2_gray, cv2.TM_CCOEFF_NORMED)
if np.any(res > 0.9):
print("Image2 is in Image1.")
were the 0.9 represents the amount of confidence required in order for the image to be classified as inside the other image. For more accuracy, you can do:
if np.any(res > 0.99):

How increase an image to a specific size by adding white transparent pixels in python (preferably using opencv)

for example:
original image's dimesion = 1080x720x4(4 as in blue , green , red and alpha channel)
required dimension = 1920x1080x4
I want White transparent pixels (255,255,255,0) to be added in the border until it reaches the required dimension.
Maybe there is numpy function to help with this?
One way using Python/OpenCV is to use copyMakeBorder as suggested by # Quang Hoang.
Input (100x116):
import cv2
# read image
img = cv2.imread("A.png", cv2.IMREAD_UNCHANGED)
img2 = cv2.copyMakeBorder(img, 50,50,50,50, borderType=cv2.BORDER_CONSTANT, value=(255,255,255,0))
cv2.imwrite("A_border.png", img2)
cv2.imshow("img2", img2)
cv2.waitKey(0)
Result (200x2016):

RGB to grayscale without cmaps

is there a way to change an image to grayscale without using cmap in matpotlib?
my function is
def grayscale(image):
img = image.copy()
r=img[:,:,0]*0.3
g=img[:,:,1]*0.59
b=img[:,:,2]*0.11
gray=r+g+b
img=np.dstack((gray,gray,gray))
return img
plt.imshow(img)
However, the image I got is just black and white, not in grayscale TT. Then when I tried using gray=r+g+b,plt.imshow(img), I got a green and yellow picture. I have tried searching everywhere to get clues and all I found was the use of cmaps. However the project I am doing doesn't allow us to use cmap.
Here is a working solution using your code - you should add your picture path in the image_path variable:
import numpy as np
from PIL import Image
import cv2
def grayscale(image):
img = np.asarray(Image.open(image))
r = img[:,:,0]*0.3
g = img[:,:,1]*0.59
b = img[:,:,2]*0.11
gray = r+g+b
return gray
image_path = "test.jpg"
img = grayscale(image_path)
cv2.imwrite('greyscale.jpg',img)
The trick was that you did not load the image in a proper way.

Reduce opacity of image using Opencv in Python

In the program given below I am adding alpha channel to a 3 channel image to control its opacity. But no matter what value of alpha channel I give there is no effect on image! Anyone could explain me why?
import numpy as np
import cv2
image = cv2.imread('image.jpg')
print image
b_channel,g_channel,r_channel = cv2.split(image)
a_channel = np.ones(b_channel.shape, dtype=b_channel.dtype)*10
image = cv2.merge((b_channel,g_channel,r_channel,a_channel))
print image
cv2.imshow('img',image)
cv2.waitKey(0)
cv2.destroyAllWindows()
I can see in the terminal that alpha channel is added and its value changes as I change it in the program, but there is no effect on the opacity of the image itself!
I am new to OpenCV so I might be missing something simple. Thanks for help!
Alpha is a channel that is used to control the opacity of an image. An alpha channel typically doesn't do anything unless you perform an action on it. It doesn't make an image transparent on its own.
Alpha is usually used to either remove unimportant areas of an image or to combine one image with another image. In the first case the image is usually simply multiplied by its alpha. This is sometimes referred to premultiplying. In this case the dark areas of the alpha channel darken the RGB and the bright areas leave the RGB untouched.
R = R*A
G = G*A
B = B*A
Here is a version of your code that might do what you want (Note- I converted to 32-bit because it's easier to use alpha channels when they are ranged from 0 to 1):
import numpy as np
import cv2
i = cv2.imread('image.jpg')
img = np.array(i, dtype=np.float)
img /= 255.0
cv2.imshow('img',img)
cv2.waitKey(0)
#pre-multiplication
a_channel = np.ones(img.shape, dtype=np.float)/2.0
image = img*a_channel
cv2.imshow('img',image)
cv2.waitKey(0)
cv2.destroyAllWindows()
The second case is used when trying to overlay an image over another image. This is a compositing operation that is often referred to as an "over" merge or a "blend" merge. In this case there is a foreground image "A" and a background image "B" and an alpha channel which could be included in the RGB images or on its own. In this case you can place A over B using:
output = (A * alpha) + (B * (1-alpha))
Actually, the answer is simple. OpenCV's imshow() function ignores the alpha channel.
If you want to see the effect of your alpha channel, save your image in PNG format (because that supports alpha channel) and display in a different viewer.
I also wrote a decorator/enhancement for imshow() here that helps visualise transparent images.

Combine more than 1 openCV images and show them in CV2.Imshow() in OpenCV Python

I am having 3 to 4 images and I am trying to combine them all into one image (put into one window) and then show them through CV2.imshow() function. But the problem is that every solution to this problem is for exactly the same dimension images, which is not my case. My images are all of different dimensions. Kindly help me out how to solve this problem? I have four images with different dimension and want output like this
|||||||||||||||||||||||||||||||||
|| Image1 || Image2 ||
||||||||||||||||||||||||||||||||||
|| Image1 || Image2 ||
||||||||||||||||||||||||||||||||||
Currently, I have code like this for two images which work on only equally sized Images
im = cv2.imread('1.png')
img = cv2.imread('2.jpg')
both = np.hstack((im,im))
cv2.imshow('imgc',both)
cv2.waitKey(10000)
Use im.resize() function of opencv to resize the image and then do the combining task.
Always use a reference dimension such as 1000 x 800 (you can change it)
import cv2
import numpy as np
list_of_img_paths = [path2,path3,path4]
im = cv2.imread(path1)
imstack = cv2.resize(im,(1000,800))
for path in list_of_img_paths:
im = cv2.imread(path)
im = cv2.resize(im,(1000,800))
# hstack to join image horizontally
imstack = np.hstack((imstack,im))
cv2.imshow('stack',imstack)
cv2.waitKey(0)

Categories

Resources