I'd like to have a Python function (using OpenCV and Numpy) which takes
a 2D image (height x width uint8 numpy array = OpenCV grayscale image)
information on where the image is relative to the camera (let's say it's at the origin of a cartesian coordinate system)
how the image is turned in 3D space
and returns
a 2D grayscale image of what the camera sees
Why I need this:
I'm trying to find a 2D-rectangle-shaped object with a pattern on it in a real photo and want to know (I know how big it is) it's position relative to the camera. My approach is to (smartly) guess the position/rotation and then compute a score for how well it fits.
I have a document that contains text and images (it's in png format) and a source image which is included in the document (source image is bigger and in better quality).
I would like to find the location (coordinates) of source image in the document.
What makes the process complicated is that the source image in the document might be unevenly scaled (eg.: more vertically than horizontally), a bit cropped (so it's smaller than source image) and slighty modified version of source image (eg.: has rounded edges).
I've tried the OpenCV template matching but with mediocre results - it doesn't handle well uneven scaling.
Is there a way to do it using python and openCV? Or another way?
1) Convert the color image to gray, do some threshold, and find contours: link
2) Find the bounding box for contours link
3) Most likely that your image will have some properties for you to pick from the list generated in step 2. For example, width and height are greater than a minimum value.
4) Now create a mask with the chosen bounding box link
5) Now compare histogram distribution between mask region and your image using chi-square distance. A distance less than 1 implies a perfect match. link
6) The bounding box gives the (x,y) coordinates, which you are looking for.
Im trying to do perspective transform on a video of a football pitch, I have found many resources for ways of doing this when all four corners of the pitch are visible however how can i do this when not all corners are visible? maybe a way of extrapolating beyond the video box?
Instead of using the four corners of the field, use the part of the field that is visible. In this image, the field is visible only to the 50 yard line.
Two corners and two midpoints are used to warp the image. Instead of warping the source image to the corners of the destination image; the source image is warped into two corners and two midpoints.
If 75% of the field is visible, warp the source image to the to that percentage of the destination image.
image source: https://www.coloradoan.com/story/sports/csu/football/2016/12/21/story-behind-boise-states-blue-football-field/95712824/
I have a distorted picture, where without distortion the point A, B C and D form a square of 1 cm * 1 cm.
I tried to use homography to correct it, but it distort the line AD and BC, as you can see in the figure.
Do you have an idea how could I correct that?
Thanks a lot!
Marie- coder beginner
PS: for info, the image is taken in a tube with an endoscope camera having a large field of view allowing to take picture of the tube almost around the camera. I will use the 1*1 cm square to estimate roots growth with several pictures taken over time.
here is my code:
import cv2
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__' :
# Read source image.
im_src = cv2.imread('points2.jpg', cv2.IMREAD_COLOR)
# Four points of the miniR image
pts_src = np.array([[742,223],[806,255],[818,507],[753,517]], dtype=float)
# Read destination image.
im_dst = cv2.imread('rectangle.jpg', cv2.IMREAD_COLOR)
# Four points of the square
pts_dst = np.array([[200,200],[1000,200],[1000,1000],[200,1000]], dtype=float)
# Calculate Homography
h, status = cv2.findHomography(pts_src, pts_dst)
# Warp source image to destination based on homography
im_out = cv2.warpPerspective(im_src, h, (im_dst.shape[1],im_dst.shape[0]))
cv2.imwrite('corrected2.jpg', im_out)
# Display images
cv2.imshow("Source Image", im_src)
cv2.imshow("Destination Image", im_dst)
cv2.imshow("Warped Source Image", im_out)
cv2.waitKey(0)
A homography is a projective transformation. As such it can only map straight lines to straight lines. The straight sides of your input curvilinear quadrangle are correctly rectified, but there is no way that you can straighten the curved sides using a projective transform.
In the photo you posted it may be reasonable to assume that the overall geometry is approximately a cylinder, and the "vertical" lines are parallel to the axis of the cylinder. So they are approximately straight, and a projective transformation (the camera projection) will map them to straight lines. The "horizontal" lines are the images of circles, or ellipses if the cylinder is squashed. A projective transformation will map ellipses (in particular, circles) into ellipses. So you could proceed by fitting ellipses. See this other answer for hints.
I found a solution using GDAL. We can use two chessboard images. One image is imaged with the device creating the distortion and remain unchanged - so with no distortion. With the help QGIS you create a file with associating distorted point to undistorted one. For that you add a Ground Control Point at each intersection using a defined grid interval (e.g. 100px) and export the resulting GCPs as pointsfile.points.
After that, you can use a batch file that a collaborator created here. It is using GDAL to geo-correct the images.
You just need to put the images that you would like to transform (jpg format) into the root directory of the repo and run bash warp.sh. This will output the re-transformed images into the out/ directory.
At http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_geometric_transformations/py_geometric_transformations.html I have seen how to geometric transform an image. Depending on the transformation, the resulting image does not fit into a rectangle. How can I crop the image in such a way that I don't have any black background (or in other words, it fits into a rectangle) in such a way that the cropped image is as large as possible? Is there a function for that in openCV?
My question is similar to Rotate image and crop out black borders. Difference is though that I am not just interested in rotated images, but any arbitrary geometric transformation.