I have a python program that detects a rectangle from the the captured Video. Now I want to project another image into the detected square (just like in this video).
I have Tried using the warpPerspective and that does not seem to be working or maybe I'm using it in the wrong way.
my present output looks like this. I want my output to look like this
I tried to overlay images after using warpPerspective:
img = cv2.imread('cola.jpg')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
background = cv2.imread('stadium.jpg')
background = cv2.cvtColor(background,cv2.COLOR_BGR2RGB)
rows,cols,ch = background.shape
pts1 = np.float32([[0,0],[974,0],[0,974],[974,974]]) # cola coords
pts2 = np.float32([[560,383],[940, 516],[5,527],[298,733]]) # stadium tile coords
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(cols,rows))
overlay = cv2.add(background, dst)
[Output image
I used OpenCV documentation
Related
I am in trouble figuring out why cv2.aruco.detectMarkers() has problems in finding more than just a few markers with my calibration board. Playing around with the paramters didn't essentially improve the quality. The dictionary is correct as I tried it with the digital template before printing.
Here is, what I do to detect CHAruco markers from a real image:
import cv2
from cv2 import aruco
#ChAruco board variables
CHARUCOBOARD_ROWCOUNT = 26
CHARUCOBOARD_COLCOUNT = 26
ARUCO_DICT = cv2.aruco.Dictionary_get(aruco.DICT_4X4_1000)
#Create constants to be passed into OpenCV and Aruco methods
CHARUCO_BOARD = aruco.CharucoBoard_create(
squaresX=CHARUCOBOARD_COLCOUNT,
squaresY=CHARUCOBOARD_ROWCOUNT,
squareLength=5, #mm
markerLength=4, #mm
dictionary=ARUCO_DICT)
#load image
img = cv2.imread('imgs\\frame25_crop.png', 1)
test image with CHAruco markers
#initialize detector
parameters = aruco.DetectorParameters_create()
parameters.adaptiveThreshWinSizeMin = 150
parameters.adaptiveThreshWinSizeMax = 186
#Find aruco markers in the query image
corners, ids, _ = aruco.detectMarkers(
image=img,
dictionary=ARUCO_DICT,
parameters=parameters)
#Outline the ChAruco markers found in our image
img = aruco.drawDetectedMarkers(
image=img,
corners=corners)
The result is the following: only 3 are markers are found, which is bad.
resulting image with found markers
Does anyone has an idea how to considerably improve the results of the detector?
Your image is flipped.
Fix it with this line of code:
img = cv2.flip(img, 0)
Without looking at your code I may say that the image quality and perspective you selected is a bit poor. You may try to work with more clear view of your markers. For instance, hang the markers on the wall take one or two step back and try to take photo of it with better light and if not necessary do not add extra rotation, and keep the contrast high :). This will probably give better results.
I have been messing around in python to see if I could "mix" two pictures together. What I mean by that is so that the image is transparent and you can see two pictures together. If that still does not make sense check out this link: (only I would mix a picture and a picture not a gif)
https://cdn.discordapp.com/attachments/652564556211683363/662770085844221963/communism.gif
Here is my code:
from PIL import Image
im1 = Image.open('oip.jpg')
im2 = Image.open('star.jpg')
bg = Image.blend(im1, im2, 0)
bg.save('star_oip_paste.jpg', quality=95)
and I get the error:
line 6, in <module> bg = Image.blend(im1, im2, 0) ValueError: images do not match
I'm not even sure if I'm using the right function for "mixing" two images together — so if I'm not, let me know.
There are several things going on here:
Your input images are both JPEG which doesn't support transparency, so you can only get a fixed blending throughout your image. I mean you can't see one image at one point and the other image at another. You will only see the same proportion of each image at each point. Is that what you want?
For example, if I take Paddington and Buckingham Palace and take 50% of each:
I get this:
If that's what you want, you need to resize the images to a common size and change this line:
bg = Image.blend(im1, im2, 0)
to
bg = Image.blend(im1, im2, 0.5) # blend half and half
If you want to paste something with transparency, so it only shows up in certain places, you need to load the overlay from a GIF or PNG with transparency and use:
background.paste(overlay, box=None, mask=overlay)
Then you can do this - note you can see different amounts of the two images at each point:
So, as a concrete example of overlaying a transparent image onto an opaque background, and starting with Paddington (400x400) and this star (500x500):
#!/usr/bin/env python3
from PIL import Image
# Open background and foreground and ensure they are RGB (not palette)
bg = Image.open('paddington.png').convert('RGB')
fg = Image.open('star.png').convert('RGBA')
# Resize foreground down from 500x500 to 100x100
fg_resized = fg.resize((100,100))
# Overlay foreground onto background at top right corner, using transparency of foreground as mask
bg.paste(fg_resized,box=(300,0),mask=fg_resized)
# Save result
bg.save('result.png')
If you want to grab an image from a website, use this:
from PIL import Image
import requests
from io import BytesIO
# Grab the star image from this answer
response = requests.get('https://i.stack.imgur.com/wKQCT.png')
# Make it into a PIL image
img = Image.open(BytesIO(response.content))
As an alternative, you could try with OpenCV (depending on your desired output)
import cv2
# Read the images
foreground = cv2.imread("puppets.png")
background = cv2.imread("ocean.png")
alpha = cv2.imread("puppets_alpha.png")
# Convert uint8 to float
foreground = foreground.astype(float)
background = background.astype(float)
# Normalize the alpha mask to keep intensity between 0 and 1
alpha = alpha.astype(float)/255
# Multiply the foreground with the alpha matte
foreground = cv2.multiply(alpha, foreground)
# Multiply the background with ( 1 - alpha )
background = cv2.multiply(1.0 - alpha, background)
# Add the masked foreground and background.
outImage = cv2.add(foreground, background)
# Display image
cv2.imshow("outImg", outImage/255)
cv2.waitKey(0)
I have a picture like this and i want to remove the background by adding a layer on top the image just like how photoshop layout works.
Original Picture
Mask/Layer
Final desired output
I am trying to do this iwth opencv's addweighed function but i am not able to get the desired output
im_overlay = cv2.imread('%s/%s.png'%(_src,camera_name.split(".")[0]))
img = cv2.addWeighted(im, 1, im_overlay, 0.0, 0)
showImage(img)
The format of the mask is strange for OpenCv to read on my system (using opencv 3.4.2). I was able to read it with cv2.IMREAD_UNCHANGED but it show me that your mask has 4 channels (I was expecting only one channel). The code below produce opposite or what you would expect:
img = cv2.imread(r"C:\Users\...\Desktop\\W1kle.jpg")
mask = cv2.imread(r"C:\Users\...\Desktop\LZdyB.png",cv2.IMREAD_UNCHANGED)
mask = mask[:,:,3]
res = cv2.bitwise_and(img,img,mask=mask)
cv2.imshow("image",res)
cv2.waitKey(0)
Hope this helps you :)
i have some problem with my task. i need get text from image using python+tesseract. But quality of image it's not highter - it`s screenshoot.
I'm using OpenCV lib and have two variant`s:
COLOR_BGR2GRAY
ADAPTIVE_THRESH_GAUSSIAN_C | THRESH_BINARY
and this variant`s working incorrect.
When i binarize image
def binarize_image(img_path, threshold=195):
"""Binarize an image."""
image_file = Image.open(img_path)
image = image_file.convert('L') # convert image to monochrome
image = np.array(image)
image = binarize_array(image, threshold)
im = Image.fromarray(image)
im.save(img_path)
# imsave(target_path, image)
def binarize_array(numpy_array, threshold=250):
"""Binarize a numpy array."""
for i in range(len(numpy_array)):
for j in range(len(numpy_array[0])):
if numpy_array[i][j] > threshold:
numpy_array[i][j] = 255
else:
numpy_array[i][j] = 0
return numpy_array
tesseract doesn`t usualy get text.
How i can resolve it`s problem ?
screenshot example
UPD: solved my problem, i need to add some pixels between two letters. on screenshot letter is white and background is black. How i can do it using numpy ?
I am using SimpleCV to stitch images. I have made some changes in SimpleCV's GitHub code and eventually got the image transformed correctly. But the problem is, the color of the image after getting transformed is changed.
I have used these images http://imgur.com/a/lrGw4. The output of my code is: http://i.imgur.com/2J722h.jpg
This is my code:
from SimpleCV import *
import cv2
import cv
img1 = Image("s.jpg")
img2 = Image("t.jpg")
dst = Image((2000, 1600))
# Find the keypoints.
ofimg = img1.findKeypointMatch(img2)
# The homography matrix.
homo = ofimg[1]
eh = dst.getMatrix()
# transform the image.
x = Image(cv2.warpPerspective(np.array((img2.getMatrix())), homo,
(eh.rows, eh.cols+300), np.array(eh), cv.INTER_CUBIC))
# blit the img1 now on coordinate (0, 0).
x = x.blit(img1, alpha=0.4)
x.save("rishi1.jpg")
It seems you're using an old revision of SimpleCV. In the latest version the way to get the homography matrix is [1]:
ofimg[0].getHomography()
Edit:
It seems the color problem you're mentioning is due to the change of color space. So please change the line you warp the image to:
x = Image(cv2.warpPerspective(np.array((img2.getMatrix())), homo,
(eh.rows, eh.cols+300), np.array(eh), cv.INTER_CUBIC), colorSpace=ColorSpace.RGB).toBGR()
I suspect what's happening is that the returned image after warping is in the BGR color space while SimpleCV by default uses the RGB color space. Please let me know how it goes.