I am studying on hologram vision. I want to placed 4 images onto black screen.
I wrote this code:
import numpy as np
import cv2
from screeninfo import get_monitors
if __name__ == '__main__':
screen = get_monitors()[0]
print(screen)
width, height = screen.width, screen.height
image = np.zeros((height, width, 3), dtype=np.float64)
image[:, :] = 0 # black screen
img = cv2.imread("newBen.png")
p = 0.25
w = int(img.shape[1])
h = int(img.shape[0])
new_img = cv2.resize(img, (w, h))
image[:h, :w] = new_img
window_name = 'projector'
cv2.namedWindow(window_name, cv2.WND_PROP_FULLSCREEN)
cv2.moveWindow(window_name, screen.x - 1, screen.y - 1)
cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
cv2.WINDOW_FULLSCREEN)
cv2.imshow(window_name, image)
cv2.waitKey()
cv2.destroyAllWindows()
But my image looking like this.
How can ı fix it?
The dtype of a normal RGB image is uint8, not float64.
image = np.zeros((height, width, 3), dtype=np.uint8)
Btw: You don't have to set image[:, :] = 0 # black screen. This is already been done by np.zeros.
Related
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 get height and width of bright part using python (opencv) ? Having 2000 of these picture and end goal is to make table with length and width values
It is primitive method. Convert to grayscale and check which points have value bigger then some "bright" color ie. 21 and it gives array True/False - using .any(axis=0) you can reduce every row to single value, using .any(axis=1) you can reduce every column to single value and then using sum() you can count how many True was in any row or column (because True/False is converted to 1/0)
import cv2
img = cv2.imread('image.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#print(img)
print('height, width, color:', img.shape)
#cv2.imshow('image', img)
#cv2.waitKey(0)
#cv2.destroyAllWindows()
print('width:', sum((img > 21).any(axis=0)))
print('height:', sum((img > 21).any(axis=1)))
For your image it gives me
width: 19
height: 27
For my image (below) it gives me
width: 23
height: 128
EDIT: Version with small change.
I set mask = (img > 21) to
calculate size
create Black&White image which better shows which points are
used to calculate size.
BTW: code ~mask inverts mask (convert True to False and False to True). It can be used also to invert image - ~img - to create negative for RGB, Grayscale or B&W.
Code:
import cv2
for filename in ['image-1.png', 'image-2.png']:
img = cv2.imread(filename)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print('height, width, color:', img.shape)
mask = (img > 21)
# display size
print(' width:', sum( mask.any(axis=0) ))
print('height:', sum( mask.any(axis=1) ))
# create Black&White version
img[ mask ] = 255 # set white
img[ ~mask ] = 0 # set black
# display Black&White version
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# write Black&White version
cv2.imwrite('BW-' + filename, img)
--->
--->
EDIT: The same result using cv2.boundingRect() instead of sum(mask.any()) - but it still needs img[ mask ] = 255 to create Black&White image.
import cv2
for filename in ['image-1.png', 'image-2.png']:
print('filename:', filename)
img = cv2.imread(filename)
#print('height, width, color:', img.shape)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#print('height, width, color:', img.shape)
mask = (img > 21)
# create Black&White version
img[ mask ] = 255 # set white
img[ ~mask ] = 0 # set black
x, y, width, height = cv2.boundingRect(img)
# display size
print(' width:', width)
print('height:', height)
# display Black&White version
#cv2.imshow('image', img)
#cv2.waitKey(0)
#cv2.destroyAllWindows()
# write Black&White version
#cv2.imwrite('BW-' + filename, img)
https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html#bounding-rectangle
EDIT: The same result using cv2.boundingRect() and cv2.threshold() - so it doesn't need mask
import cv2
for filename in ['image-1.png', 'image-2.png']:
print('filename:', filename)
img = cv2.imread(filename)
#print('height, width, color:', img.shape)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#print('height, width, color:', img.shape)
ret, img = cv2.threshold(img, 21, 255, cv2.THRESH_BINARY) # the same 21 as in `mask = (img > 21)`
x, y, width, height = cv2.boundingRect(img)
# display size
print(' width:', width)
print('height:', height)
# display Black&White version
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# write Black&White version
#cv2.imwrite('BW-' + filename, img)
https://docs.opencv.org/3.4/d7/d4d/tutorial_py_thresholding.html
https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html
https://www.learnopencv.com/opencv-threshold-python-cpp/
https://www.geeksforgeeks.org/python-thresholding-techniques-using-opencv-set-1-simple-thresholding/
i'm trying to resize an image to a default value, filling the entire space.
I've tried to create a blank background, pasting the image i have but i'm having errors:
# image_toresize it's the image I want to apply over the background
# the image im using for the background
blank_image = np.zeros((600,900,3), np.uint8)
blank_image = (255,255,255)
l_img = blank_image.copy()
x_offset = y_offset = 0
height, width = image_toresize.shape[:2]
l_img[0:height, 0:width] = image_toresize.copy()
this error
ValueError: could not broadcast input array from shape (90,657) into shape (90,657,3)
What can i do?
Try below code:
image_toresize = cv2.imread('flower5.jpg')
height, width = image_toresize.shape[:2]
blank_image = np.zeros((600,900,3), np.uint8)
blank_image[:,:] = (255,255,255)
l_img = blank_image.copy() # (600, 900, 3)
x_offset = y_offset = 100
# Here, y_offset+height <= blank_image.shape[0] and x_offset+width <= blank_image.shape[1]
l_img[y_offset:y_offset+height, x_offset:x_offset+width] = image_toresize.copy()
cv2.imshow('img', l_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Output:
Figure 1: Original Image
Figure 2: Above image added to a white empty background
I want to add glasses PNG image onto another image, but i get the PNG image with white background which hides the face.
I need to know what i did wrong please.
Original face image
Original glasses image
Expected result
import cv2
import numpy
img = cv2.imread("barack-obama.jpg")
lunette = cv2.imread("lunette.png", cv2.IMREAD_UNCHANGED)
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eyes = eye_cascade.detectMultiScale(img, scaleFactor = 1.1, minNeighbors = 5)
r = 500.0 / img.shape[1]
dim = (500, int(img.shape[0] * r))
resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
grey = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(grey, 1.3, 5)
for (x,y,w,h) in faces:
roi_grey = grey[y:y+h, x:x+w]
roi_color = resized[y:y + h, x:x + w]
eyes = eye_cascade.detectMultiScale(roi_grey)
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
lunette = cv2.resize(lunette , (w,h))
w, h, c = lunette.shape
for i in range(0, w):
for j in range(0, h):
if lunette[i, j][0] != 0:
resized[y + i, x + j] = lunette[i, j][1]
#help please
cv2.imshow('img',resized)
cv2.waitKey(0)
Here is one way to do that in Python/OpenCV/Numpy:
Read the background image (Obama)
Read the overlay image (glasses) unchanged
Extract the base BGR channels from the overlay image
Extract the alpha channel from the overlay image as a mask
Insert the BGR channels of the overlay into the background image at the desired location
Insert the mask into a black image the size of the background image at the desired location
Use Numpy where to composite the new background and overlay images using the new mask image
Save the result
import cv2
import numpy as np
# read background image
img = cv2.imread("obama.jpg")
ht, wd = img.shape[:2]
# read overlay image
img2 = cv2.imread("sunglasses.png", cv2.IMREAD_UNCHANGED)
ht2, wd2 = img2.shape[:2]
# extract alpha channel as mask and base bgr images
bgr = img2[:,:,0:3]
mask = img2[:,:,3]
# insert bgr into img at desired location and insert mask into black image
x = 580
y = 390
bgr_new = img.copy()
bgr_new[y:y+ht2, x:x+wd2] = bgr
mask_new = np.zeros((ht,wd), dtype=np.uint8)
mask_new[y:y+ht2, x:x+wd2] = mask
mask_new = cv2.cvtColor(mask_new, cv2.COLOR_GRAY2BGR)
# overlay the base bgr image onto img using mask
result = np.where(mask_new==255, bgr_new, img)
# save results
cv2.imwrite('obama_glasses.jpg', result)
# display results
cv2.imshow('bgr', bgr)
cv2.imshow('mask', mask)
cv2.imshow('bgr_new', bgr_new)
cv2.imshow('mask_new', mask_new)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result:
You can use cvzone library for solve this problem.
install cvzone library
pip install cvzone
import cvzone in your project
import cvzone
imread your emoji with following format
lunette = cv2.imread("lunette.png", cv2.IMREAD_UNCHANGED)
now replace the your emoji like this:
YOUR BACKGROUND PICTURE = cvzone.overlayPNG(YOUR BACKGROUND PICTURE, lunette , [x, y])
How can I crop a concave polygon from an image. My Input image look like
.
and the coordinates of closed polygon are
[10,150],[150,100],[300,150],[350,100],[310,20],[35,10]. I want region bounded by concave polygon to be cropped using opencv. I searched for other similar questions but I did not able to find correct answer. That's why I am asking it ? Can you help me.
Any help would be highly appreciated.!!!
Steps
find region using the poly points
create mask using the poly points
do mask op to crop
add white bg if needed
The code:
# 2018.01.17 20:39:17 CST
# 2018.01.17 20:50:35 CST
import numpy as np
import cv2
img = cv2.imread("test.png")
pts = np.array([[10,150],[150,100],[300,150],[350,100],[310,20],[35,10]])
## (1) Crop the bounding rect
rect = cv2.boundingRect(pts)
x,y,w,h = rect
croped = img[y:y+h, x:x+w].copy()
## (2) make mask
pts = pts - pts.min(axis=0)
mask = np.zeros(croped.shape[:2], np.uint8)
cv2.drawContours(mask, [pts], -1, (255, 255, 255), -1, cv2.LINE_AA)
## (3) do bit-op
dst = cv2.bitwise_and(croped, croped, mask=mask)
## (4) add the white background
bg = np.ones_like(croped, np.uint8)*255
cv2.bitwise_not(bg,bg, mask=mask)
dst2 = bg+ dst
cv2.imwrite("croped.png", croped)
cv2.imwrite("mask.png", mask)
cv2.imwrite("dst.png", dst)
cv2.imwrite("dst2.png", dst2)
Source image:
Result:
You can do it in 3 steps:
Create a mask out of the image
mask = np.zeros((height, width))
points = np.array([[[10,150],[150,100],[300,150],[350,100],[310,20],[35,10]]])
cv2.fillPoly(mask, points, (255))
Apply mask to original image
res = cv2.bitwise_and(img,img,mask = mask)
Optionally you can remove the crop the image to have a smaller one
rect = cv2.boundingRect(points) # returns (x,y,w,h) of the rect
cropped = res[rect[1]: rect[1] + rect[3], rect[0]: rect[0] + rect[2]]
With this you should have at the end the image cropped
UPDATE
For the sake of completeness here is the complete code:
import numpy as np
import cv2
img = cv2.imread("test.png")
height = img.shape[0]
width = img.shape[1]
mask = np.zeros((height, width), dtype=np.uint8)
points = np.array([[[10,150],[150,100],[300,150],[350,100],[310,20],[35,10]]])
cv2.fillPoly(mask, points, (255))
res = cv2.bitwise_and(img,img,mask = mask)
rect = cv2.boundingRect(points) # returns (x,y,w,h) of the rect
cropped = res[rect[1]: rect[1] + rect[3], rect[0]: rect[0] + rect[2]]
cv2.imshow("cropped" , cropped )
cv2.imshow("same size" , res)
cv2.waitKey(0)
For the colored background version use the code like this:
import numpy as np
import cv2
img = cv2.imread("test.png")
height = img.shape[0]
width = img.shape[1]
mask = np.zeros((height, width), dtype=np.uint8)
points = np.array([[[10,150],[150,100],[300,150],[350,100],[310,20],[35,10]]])
cv2.fillPoly(mask, points, (255))
res = cv2.bitwise_and(img,img,mask = mask)
rect = cv2.boundingRect(points) # returns (x,y,w,h) of the rect
im2 = np.full((res.shape[0], res.shape[1], 3), (0, 255, 0), dtype=np.uint8 ) # you can also use other colors or simply load another image of the same size
maskInv = cv2.bitwise_not(mask)
colorCrop = cv2.bitwise_or(im2,im2,mask = maskInv)
finalIm = res + colorCrop
cropped = finalIm[rect[1]: rect[1] + rect[3], rect[0]: rect[0] + rect[2]]
cv2.imshow("cropped" , cropped )
cv2.imshow("same size" , res)
cv2.waitKey(0)
For the blured image background version use the code like this:
img = cv2.imread(img_path)
box = <box points>
# -- background
blur_bg = cv2.blur(img, (h, w))
mask1 = np.zeros((h, w, 3), np.uint8)
mask2 = np.ones((h, w, 3), np.uint8) * 255
cv2.fillPoly(mask1, box, (255, 255, 255))
# -- indexing
img_idx = np.where(mask1 == mask2)
bg_idx = np.where(mask1 != mask2)
# -- fill box
res = np.zeros((h, w, 3), np.int64)
res[img_idx] = img[img_idx]
res[bg_idx] = blur_bg[bg_idx]
res = res[y1:y2, x1:x2, :]