Overlay images of different size and no of channels - python

I'm trying to overlay random images (natural scene images should be overlayed with sign images) using OpenCV and Python. They can vary in size, file extension and no. of channels (and many more, I guess). So I'm resizing the sign images according to the size of the natural scene image and put them onto the latter.
I have implemented fireant's code found here: overlay a smaller image on a larger image python OpenCv
But it only works for images with 4 channels.
Using cv2.addWeighted() always crops the larger image (scene image) to the size of the smaller image (sign image). Has anybody an idea how to do that? Help is highly appreciated.
EDIT: See the expected output below. At first the, escape route sign and the background are separate images.
And this is my code, it is working, but since a lot of my images seem to have only 3 channels, I would like to get it working for those also.
import cv2
import time
import math
import os
pathSigns = "/home/moritz/Schreibtisch/Signs"
pathScenes = "/home/moritz/Schreibtisch/Scenes"
i = 0
for fSigns in os.listdir(pathSigns):
fSigns = os.path.join(pathSigns, fSigns)
s_img = cv2.imread(fSigns, -1)
for fScenes in os.listdir(pathScenes):
try:
l_img = cv2.imread(os.path.join(pathScenes, fScenes))
l_height, l_width, l_channels = l_img.shape
TARGET_PIXEL_AREA = (l_height * l_width) * 0.05
ratio = float(s_img.shape[1]) / float(s_img.shape[0])
s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
s_new_w = int((s_new_h * ratio) + 0.5)
s_img = cv2.resize(s_img,(s_new_w, s_new_h))
x_offset=y_offset=50
# l_img[y_offset:y_offset+s_img.shape[0],
x_offset:x_offset+s_img.shape[1]] = s_img
y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]
height, width, channels = s_img.shape
if channels <= 3:
alpha_s = s_img[:, :, 2] / 255.0
alpha_l = 1.0 - alpha_s
else:
alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s
for c in range(0, 3):
l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] +
alpha_l * l_img[y1:y2, x1:x2, c])
fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) +
".png"
i += 1
cv2.imwrite(fResult, l_img)
except IndexError:
pass

thanks to #DanMaĆĄek hint and How to crop or remove white background from an image, I have worked out a solution. The following code will first remove white background from the smaller image, then set all images to 4 channels and then overlay the larger image with a smaller image. Works for me.
import cv2
import time
import math
import os
import numpy as np
pathSigns = "/home/moritz/Schreibtisch/Signs"
pathScenes = "/home/moritz/Schreibtisch/Scenes"
i = 0
for fSigns in os.listdir(pathSigns):
fSigns = os.path.join(pathSigns, fSigns)
s_img = cv2.imread(fSigns, -1)
s_height, s_width, s_channels = s_img.shape
# crop image
gray = cv2.cvtColor(s_img, cv2.COLOR_BGR2GRAY)
th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)
_, cnts, _ = cv2.findContours(morphed, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnt = sorted(cnts, key=cv2.contourArea)[-1]
x,y,w,h = cv2.boundingRect(cnt)
s_img = s_img[y:y+h, x:x+w]
# set channels to 4
if s_channels < 4:
s_img = cv2.cvtColor(s_img, cv2.COLOR_BGR2BGRA)
for fScenes in os.listdir(pathScenes):
try:
l_img = cv2.imread(os.path.join(pathScenes, fScenes))
l_height, l_width, l_channels = l_img.shape
if l_channels < 4:
l_img = cv2.cvtColor(l_img, cv2.COLOR_BGR2BGRA)
TARGET_PIXEL_AREA = (l_height * l_width) * 0.05
ratio = float(s_img.shape[1]) / float(s_img.shape[0])
s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
s_new_w = int((s_new_h * ratio) + 0.5)
s_img = cv2.resize(s_img,(s_new_w, s_new_h))
x_offset=y_offset=50
y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]
alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s
for c in range(0, 3):
l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] + alpha_l *
l_img[y1:y2, x1:x2, c])
fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) + ".png"
i += 1
cv2.imwrite(fResult, l_img)
except IndexError:
pass

Related

ValueError: Could not broadcast when trying to resize and center image

I have written a simple function that creates an video frame from an image.
Basically, if the image is bigger than the frame, if the aspect ratio of the image is greater than or equal to the aspect ratio of the frame, the image will be resized to fit the width while keeping its aspect ratio, else the image is resized to fit height while maintaining its aspect ratio.
Then if the (resized) image has four channels (it has an alpha channel), the image will be converted to its alpha composite with a black image (the color channels will become the product of the original color channels and the alpha channel).
Then the image is moved to the center of frame. The frame is always a black three channel image.
Yep it is quite verbose to describe the process in English, but the function is actually quite simple in code:
import cv2
import numpy as np
def make_frame(img, fw, fh):
h, w, c = img.shape
if w > fw or h > fh:
if w/h >= fw/fh:
h = round(fw * h / w)
w = fw
else:
w = round(fh * w / h)
h = fh
img = cv2.resize(img, (h, w), interpolation = cv2.INTER_AREA)
h, w, c = img.shape
dw, dh = round((fw - w) / 2), round((fh - h) / 2)
frame = np.zeros((fh, fw, 3), dtype=np.uint8)
if c == 3:
frame[dh:dh+h, dw:dw+w] = img
else:
alpha = img[..., 3]/255
bgr = img[..., :3]
frame[dh:dh+h, dw:dw+w] = bgr * alpha[...,np.newaxis]
return frame
I don't understand how can it raise exceptions like this:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-128-0b3cf7332ed5> in <module>
----> 1 make_frame(img, 1280, 720)
<ipython-input-127-d57a541f7e04> in make_frame(img, fw, fh)
18 alpha = img[..., 3]/255
19 bgr = img[..., :3]
---> 20 frame[dh:dh+h, dw:dw+w] = bgr * alpha[...,np.newaxis]
21 return frame
ValueError: could not broadcast input array from shape (721,720,3) into shape (720,720,3)
I have managed to make an image that when passed as argument to the above function, will perfectly reproduce the above error:
The image is a transparent PNG file with resolution of 1081*1080. Stack Overflow automatically converts the image so the image downloaded from Stack Overflow may fail to reproduce the exception.
Download the original version from Google Drive for perfect reproducibility.
What might caused the exception? Is there a bug in my code?
Steps to reproduce:
img = cv2.imread(file_path, cv2.IMREAD_UNCHANGED)
make_frame(img, 1280, 720)
Interestingly, if you crop the image to 1080*1080, and do the same steps above, it will work just fine...
Indeed the problem was the call to resize the images. The dimension parameter is flipped. After fixing that, the problem was solved.
Anyways here is the whole script where the function is from:
import cv2
import numpy as np
import os
import skimage.exposure
FFMPEG = 'D:/ffmpeg/ffmpeg.exe'
def imread_transparent(filename):
img = cv2.imread(filename, cv2.IMREAD_UNCHANGED)
if img.shape[2] == 4:
return img
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
morph = cv2.threshold(gray, 11, 255, cv2.THRESH_BINARY)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
for mode in (cv2.MORPH_OPEN, cv2.MORPH_CLOSE, cv2.MORPH_ERODE):
morph = cv2.morphologyEx(morph, mode, kernel, borderType=cv2.BORDER_CONSTANT, borderValue=0)
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
contour = np.zeros_like(gray)
cv2.drawContours(contour, [big_contour], 0, 255, -1)
blur = cv2.GaussianBlur(contour, (5,5), sigmaX=0, sigmaY=0, borderType = cv2.BORDER_DEFAULT)
mask = skimage.exposure.rescale_intensity(blur, in_range=(127.5,255), out_range=(0,255))
result = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
result[:,:,3] = mask
return result
def rotate_image(image, angle):
h, w = image.shape[:2]
cX, cY = (w // 2, h // 2)
M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
cos = np.abs(M[0, 0])
sin = np.abs(M[0, 1])
nW = round((h * sin) + (w * cos))
nH = round((h * cos) + (w * sin))
M[0, 2] += (nW / 2) - cX
M[1, 2] += (nH / 2) - cY
return cv2.warpAffine(image, M, (nW, nH))
def remove_border(image):
if image.shape[2] == 3:
return image
y,x = image[:,:,3].nonzero()
minx = np.min(x)
miny = np.min(y)
maxx = np.max(x)
maxy = np.max(y)
return image[miny:maxy, minx:maxx]
def make_frame(img, fw, fh):
h, w, c = img.shape
if w > fw or h > fh:
if w/h >= fw/fh:
h = round(fw * h / w)
w = fw
else:
w = round(fh * w / h)
h = fh
img = cv2.resize(img, (w, h), interpolation = cv2.INTER_AREA)
dw, dh = round((fw - w) / 2), round((fh - h) / 2)
frame = np.zeros((fh, fw, 3), dtype=np.uint8)
if c == 3:
frame[dh:dh+h, dw:dw+w] = img
else:
alpha = img[..., 3]/255
bgr = img[..., :3]
frame[dh:dh+h, dw:dw+w] = bgr * alpha[...,np.newaxis]
return frame
def huerotvid(imagefile, outfile, n=256, loops=1, fps=24, rotate=False, frame_width=None, frame_height=None, bitrate='5M'):
assert 0 < n <= 256
img = imread_transparent(imagefile)
height, width = img.shape[:2]
if frame_width is None:
frame_width = width
if frame_height is None:
frame_height = height
assert frame_width > 0 and frame_height > 0
hsv = np.zeros((height, width, 4), dtype=np.uint8)
hsv[..., :3] = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL)
hsv[..., 3] = img[..., 3]
h = hsv[..., 0]
chsv = hsv.copy()
file_name = imagefile.split('/')[-1][::-1].split('.', 1)[1][::-1]
tmp_folder = os.environ['tmp']
for i in range(n):
chsv[..., 0] = (h + round(i/n*256)) % 256
frame = np.zeros((height, width, 4), dtype=np.uint8)
frame[..., :3] = cv2.cvtColor(chsv[..., :3], cv2.COLOR_HSV2BGR_FULL)
frame[..., 3] = img[..., 3]
if rotate:
frame = remove_border(rotate_image(frame, i*360/n))
frame = make_frame(frame, frame_width, frame_height)
cv2.imwrite('{}/{}_{}.png'.format(tmp_folder, file_name, i), frame)
command = '{} -y -stream_loop {} -framerate {} -hwaccel cuda -hwaccel_output_format cuda -i {}/{}_%d.png -c:v h264_nvenc -b:v {} -vf scale={}:{} {}'
os.system(command.format(FFMPEG, loops-1, fps, tmp_folder, file_name, bitrate, frame_width, frame_height, outfile))
for i in range(n):
os.remove('{}/{}_{}.png'.format(tmp_folder, file_name, i))

How to store directories of image as target name and image array to DataFrame pandas

I have an image directories like this:
and I have a code like this following:
base_dir = 'dataset/'
data = []
target = []
for folder in os.listdir(base_dir):
files = os.listdir(os.path.join(base_dir, folder))
for batch in files:
img = cv2.imread(os.path.join(base_dir, folder, batch))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 170, 255, cv2.THRESH_BINARY)
canny = cv2.Canny(thresh,50,100)
circles = cv2.HoughCircles(canny,cv2.HOUGH_GRADIENT,1,10000,param1=50,param2=30,minRadius=0,maxRadius=1000)
height,width = gray.shape
r = 0
mask = np.zeros((height,width), np.uint8)
for i in circles[0,:]:
cv2.circle(img,(i[0],i[1]),i[2],(0,255,0),3)
cv2.circle(mask,(i[0],i[1]),i[2],(255,255,255),thickness=-1)
blank_image = img[:int(i[1]),:int(i[1])]
masked_data = cv2.bitwise_and(gray, gray, mask=mask)
_,thresh = cv2.threshold(mask,1,255,cv2.THRESH_BINARY)
contours = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
x,y,w,h = cv2.boundingRect(contours[0][0])
crop = masked_data[y:y+h,x:x+w]
r = i[2]
crop_dim =cv2.cvtColor(crop, cv2.COLOR_RGB2BGR)
# liang's code for reference
def daugman_normalization(image, height, width, r_in, r_out):
thetas = np.arange(0, 2 * np.pi, 2 * np.pi / width) # Theta values
r_out = r_in + r_out
# Create empty flatten image
flat = np.zeros((height,width, 3), np.uint8)
circle_x = int(image.shape[0] / 2)
circle_y = int(image.shape[1] / 2)
for i in range(width):
for j in range(height):
theta = thetas[i] # value of theta coordinate
r_pro = j / height # value of r coordinate(normalized)
# get coordinate of boundaries
Xi = circle_x + r_in * np.cos(theta)
Yi = circle_y + r_in * np.sin(theta)
Xo = circle_x + r_out * np.cos(theta)
Yo = circle_y + r_out * np.sin(theta)
# the matched cartesian coordinates for the polar coordinates
Xc = (1 - r_pro) * Xi + r_pro * Xo
Yc = (1 - r_pro) * Yi + r_pro * Yo
color = image[int(Xc)][int(Yc)] # color of the pixel
flat[j][i] = color
return flat
try:
image_nor = daugman_normalization(crop_dim,30,180,50,50)
except:
image_nor = daugman_normalization(crop_dim,30,180,45,45)
image_nor = image_nor[:,:,0]
image_nor = np.asarray(image_nor)
image_nor = image_nor.flatten()
data.append(image_nor)
nama_target = os.path.splitext(folder)
target.append(nama_target)
all_imgs = []
for img in data:
all_imgs.append(img)
all_imgs.append(target)# all_imgs.append(label)
columns = []
x = range(1,5400)
for n in x:
columns.append(n)
columns.append("target")
df = pd.DataFrame(all_imgs,columns = columns)
df
and the dataframe output like this:
but, I wanna make a "target" column with the folder name (directories of image), and the image have 5400 pixel with total all column 5401 (5400 for the value of image's pixel and 1 another column for target name)
and my expect DataFrame output with the following image:
How can I change the code with the output like this?
Thank you for advance!

Convert RGB image to black and white

I have the following RGB image (shape of (3, 50, 200)):
I want to reduce dimensions by converting the image to pure black and white (this image looks black and white, but actually it has 3 channels as I mentioned).
I made (with help from the internet) the following function:
def rgb2gray(rgb):
r, g, b = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
gray = (0.2989 * r + 0.5870 * g + 0.1140 * b)
for x in range(rgb.shape[1]):
for y in range(rgb.shape[0]):
if gray[y][x]>128: #if bright
gray[y][x] = 255.0 #white
else:
gray[y][x] = 0.0 #black
return gray
Then I ran:
im = cv2.imread("samples/55y2m.png")
print(im.shape)
print(rgb2gray(im).shape)
plt.imshow(rgb2gray(im))
And got the following output:
(50, 200, 3) #for the input
(50, 200) #for the output
Why the image is yellow and purple, and how can I change it to black and white?
p.s. I tried to change the function to:
def rgb2gray(rgb):
r, g, b = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
gray = (0.2989 * r + 0.5870 * g + 0.1140 * b)
for x in range(rgb.shape[1]):
for y in range(rgb.shape[0]):
if gray[y][x]>128:
rgb[y][x] = 255.0 #changed
else:
rgb[y][x] = 0.0 #changed
return rgb #changed
And I actually got pure black and white image, but it was 3 channels (RGB). So I tried to remove the last axis, and got purple and yellow again.
You don't need this:
r, g, b = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
gray = (0.2989 * r + 0.5870 * g + 0.1140 * b)
because your image is already grayscale, which means R == G == B, so you may take GREEN channel (or any other if you like) and use it.
And yeah, specify the colormap for matplotlib:
plt.imshow(im[:,:,1], cmap='gray')

Labyrinth recognition is slow and recognition is not always acurate

I'm making a Python script that:
gets the image from file
Looks for a papersheet (done by openCV)
Warps the image
crops the margins of papersheet
Looks for lowest amount of white pixels in a single row of pixels which makes up for width/height of a single field of a grid (goes pixel by pixel)
Recreates the labyrinth based on what are the average pixel RGB Values in each field (goes pixel by pixel) and saves it to file
It shows me the grid of 0 and 1s in the CLI
When I do it on original image (5.2MB, 4000x3000) , it takes up to 20 seconds (although I have pretty snappy 8 core ryzen cpu), actually I only need the output (0 or 1 grid). How can I speed up the process as it will run on raspberry pi and it needs to take only about few seconds to finish? I know that the code is quite long, however it's split into sections that are described so it should be fairly easy to read.
#LIBRARY IMPORT
import math
import turtle
import time
import sys
from collections import deque
import numpy as np
from skimage import exposure
import argparse
import imutils
import cv2
from PIL import Image, ImageDraw
#LOAD THE FIRST IMAGE
image = cv2.imread("./image3.jpg")
ratio = image.shape[0] / 600.0
orig = image.copy()
image = imutils.resize(image, height = 600)
#Range of the colors of paper
lower = [160, 160, 160]
upper = [255,255,255]
#create array from ranges
lower = np.array(lower, dtype="uint8")
upper = np.array(upper, dtype="uint8")
#finding contours
mask = cv2.inRange(image, lower, upper)
output = cv2.bitwise_and(image, image, mask=mask)
ret,thresh = cv2.threshold(mask, 40, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
contours = max(contours, key = cv2.contourArea)
cnt = contours
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
for c in [contours]:
#contour approximation
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.01 * peri, True)
#crop of contour with 4 points
if len(approx) == 4:
screenCnt = approx
break
img = cv2.drawContours(image,[screenCnt],0,(0,0,255),2)
print(screenCnt)
pts = screenCnt.reshape(4, 2)
rect = np.zeros((4, 2), dtype = "float32")
s = pts.sum(axis = 1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
diff = np.diff(pts, axis = 1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
rect *= ratio
(tl, tr, br, bl) = rect
widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
maxWidth = max(int(widthA), int(widthB))
maxHeight = max(int(heightA), int(heightB))
dst = np.array([
[0, 0],
[maxWidth - 1, 0],
[maxWidth - 1, maxHeight - 1],
[0, maxHeight - 1]], dtype = "float32")
M = cv2.getPerspectiveTransform(rect, dst)
warp = cv2.warpPerspective(orig, M, (maxWidth, maxHeight))
warp = imutils.resize(warp)
cv2.imshow("image", image)
cv2.moveWindow("image",0,450)
cv2.imwrite("warp.jpg",warp)
#warping of found labyrinth
warp = cv2.imread("warp.jpg",0)
warp = cv2.medianBlur(warp,5)
ret,warp = cv2.threshold(warp,170,255,cv2.THRESH_BINARY)
cv2.imwrite("warp.jpg",warp)
image_file = "warp.jpg"
im = Image.open(image_file)
width, height = im.size
T = height*(5/210)
B = height-(height*(5/210))
L = width*(5/210)
R = width-(width*(5/210))
im_crop = im.crop((L, T, R, B))
im=im_crop
im_crop.save('warp.png', quality=100)
white=0
#finding field-size
im = Image.open("warp.png")
width, height = im.size
minimalGridWidth2 = width
minimalGridWidth = width
MaximumGridWidth = width
for y in range (0, height):
for x in range (0, width):
if im.getpixel((x,y)) > 200:
white = white+1
if white <= minimalGridWidth:
minimalGridWidth = white
#checks out how many X how many fields the labirynt has, checks what's the average value (more black or more white) is there on that field and recreates the new "ideal" labyrinth from this data
gridWidth = int(round(width/minimalGridWidth))
gridHeight = int(round(height/minimalGridWidth))
print(gridWidth)|
print(gridHeight)
newHeight = 0
newWidth = 0
newHeight=(minimalGridWidth*gridHeight)
newWidth=(minimalGridWidth*gridWidth)
print(minimalGridWidth)
print(newWidth)
print(newHeight)
im = im.resize((newWidth, newHeight), Image.ANTIALIAS)
i=0
x, y = gridWidth, gridHeight
pixelcount = [[0 for x in range(0,gridWidth)] for y in range(0,gridHeight)]
pixelavg = [[0 for x in range(0,gridWidth)] for y in range(0,gridHeight)]
print(pixelcount)
for y in range (0, gridHeight):
for x in range (0, gridWidth):
i=0
pixel=0
for v in range (0, minimalGridWidth):
for w in range (0, minimalGridWidth):
pixel=pixel+im.getpixel((((x*minimalGridWidth)+w),((y*minimalGridWidth)+v)))
i=i+1
if (pixel/i)<127:
pixelavg[y][x]=1
elif (pixel/i)>127:
pixelavg[y][x]=0
print(np.array(pixelavg))
y,x,v,w,i=0,0,0,0,0
im2 = Image.new('RGB',(newWidth,newHeight),'white')
for y in range (0, gridHeight):
for x in range (0, gridWidth):
for v in range (0, minimalGridWidth):
for w in range (0, minimalGridWidth):
pixelx=pixelavg[y][x]
if pixelx==0:
pixelDoc=(255,255,255)
if pixelx==1:
pixelDoc=(0,0,0)
Xw=((x*minimalGridWidth)+w)
Yh=((y*minimalGridWidth)+v)
im2.putpixel((Xw,Yh),pixelDoc)
im2.save('warp3.png',quality=100)
imx=cv2.imread('warp3.png',0)
cv2.imshow('finito',imx)
cv2.imwrite('koniec.png',imx)
cv2.moveWindow("finito",750,450)
warp=cv2.imread("warp.png",0)
cv2.imshow("warp",warp)
cv2.moveWindow("warp",450,450)
When you are concerned with performance or looking to optimize code, it can help to profile your program.
You could use Python's profiler or an IDE with a profiler like PyCharm.
When profiling your code on a 4000x2665 image, I found the following:
As you can see, the getpixel and putpixel functions take ~60% of the total execution time.
This makes sense, as they are called for every image pixel in a nested loop:
for y in range (0, height):
white = 0
for x in range (0, width):
if im.getpixel((x,y)) > 200:
white = white+1
if white <= minimalGridWidth:
minimalGridWidth = white
The above code can be fixed by replacing the nested loops by image-wide operations.
np_im = np.array(im)
white_per_row = np.sum(np_im > 200, axis=1)
minimalGridWidth = np.min(white_per_row)
Replacing this single operation cuts down the total execution time by 5644 ms or ~32%

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

Categories