opencv align two images by keypoints [closed] - python

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
The community reviewed whether to reopen this question 9 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have two images
image1(dog): Download link
image2 (bird):
I want to align image2 on image1 by keypoints. So the goal that both keypoints overlaps and the bird image is resized and scaled on top of the dog image.
Image 1 with keypoints:
Image two with keypoints:
This are my keypoints (csv file). The coordinates are x and y in the original image (download links at top):
bird_x,bird_y,dog_x,dog_y
0,43,265,48
88,12,297,29
172,1,332,23
211,17,349,32
283,60,378,60
143,109,321,98
How can I do this with opencv and python?

A quick rough way to do it is by resizing the smaller image to the bounding box formed by the keypoints of the bigger image.
import cv2
import numpy as np
img_dog = cv2.imread("akita.jpg")
img_bird = cv2.imread("gull.png")
#Reconstruct the keypoints
bird_keypoints = ((0,43), (88,12), (172,1), (211,17), (283,60), (143,109))
dog_keypoints = ((265,48), (297,29), (332,23), (349,32), (378,60), (321, 98))
#New dimension of the smaller image - calculate keypoints max x and y range
min_x = min([p[0] for p in dog_keypoints])
max_x = max([p[0] for p in dog_keypoints])
min_y = min([p[1] for p in dog_keypoints])
max_y = max([p[1] for p in dog_keypoints])
scale_height = max_y - min_y
scale_width = max_x - min_x
center = (0.5*(min_x + max_x), 0.5*(min_y + max_y))
#resize smaller image
img_bird_scaled = cv2.resize(img_bird, (scale_width,scale_height),
interpolation=cv2.INTER_AREA)
#overwrite part of the dog image with the new scaled smaller image
img_dog[min_y:max_y, min_x:max_x] = img_bird_scaled
cv2.imshow("test", img_dog)
If you need to paste only the bird without the background, you will have to deal with the alpha channel.

Related

Is there a direct way to crop an irregular dimensioned / non rectangular object in image where background area should be transparent [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am doing object detection which gives specific polygonal points which I want to crop out from the original image, but apart from the region of interest all the background should be transperent(not just black/white color obtained post bitwise_and operation from ROI). Want to know if it is possible to crop it in that way rather than tweaking the alpha value to decrease the opacity of the background.
That can be done by making a white filled mask on a black background in Python/OpenCV using fillPoly() from your polygon points. Then put the mask into the alpha channel of the image.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread("efile.jpg")
points = np.array( [[ [693,67], [23,85], [62,924], [698,918] ]] )
# draw white filled polygon from points on black background as mask
mask = np.zeros_like(img)
cv2.fillPoly(mask, points, (255,255,255))
mask = mask[:,:,0]
# put mask into alpha channel of image
result = img.copy()
result = cv2.cvtColor(result, cv2.COLOR_BGR2BGRA)
result[:,:,3] = mask
# write results
cv2.imwrite("efile_mask.jpg", mask)
cv2.imwrite("efile_transparent.png", result)
# display it
cv2.imshow("efile_mask", mask)
cv2.imshow("efile_transparent", result)
cv2.waitKey(0)
Result:

Manipulate images with Python for image quiz (big pixels areas) [duplicate]

This question already has answers here:
How to pixelate a square image to 256 big pixels with python?
(4 answers)
Closed 2 years ago.
I want to manipulate some images with Python for a little quiz game. The quiz player should guess the image.
I think an image with only big pixel areas would be fine. I want a similar result like this: https://www.ixxiyourworld.com/media/2387631/ixsp110-van-gogh-petrol-pixel-03.jpg
Lets try PIL to first downscale the image massively to a given kernel size, then upscale with NEAREST back to the same size -
from PIL import Image
from numpy import asarray
img = Image.open("van_gogh.jpg", mode='r')
factor = 100
kernel = (img.height//factor, img.width//factor)
pixelated = img.resize(kernel,resample=Image.BICUBIC) #downsample
pixelated = pixelated.resize(img.size,Image.NEAREST) #upsample
#Grids
grid_color = [255,255,255]
dx, dy = factor, factor
g = np.asarray(pixelated).copy()
g[:,::dy,:] = grid_color
g[::dx,:,:] = grid_color
pixelated2 = Image.fromarray(g)
pixelated2
Increasing the factor here, will pixelate the image further.
factor = 100

Distance between two points in OpenCv based on known measurement [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 years ago.
Improve this question
I have an image in which, I have two set of coordinates between which I have draw a line.
#Get image
im_res = requests.get(image_url)
img = Image.open(BytesIO(im_res.content))
img = np.asarray(img)
#Draw first line
lineThickness = 3
cv.line(img, (ax, ay), (bx, by), (0,255,0), lineThickness)
#Draw second line
lineThickness = 3
cv.line(img, (cx, cy), (dx, dy), (0,255,0), lineThickness)
cv.imshow("Image", img)
cv.waitKey(0)
cv.destroyAllWindows()
Coordinates are A,B,C & D. I know the distance between C to D. However, the distance between A to B is unknown. What is the best way to calculate this in OpenCv?
Is there an OpenCv specific function or method to do this? Especially the distance we are taking about is in pixels? I am sorry if this question is foolish, I really don't want to to end up getting wrong values due to lack of understanding in this topic.
I saw certain references to cv2.norm() and cv2.magnitude() as solution to this problem. However, I quite didnt't understand how to choose for my situation, keeping in mind in this case the distance is within an image/photo.
Compute Euclidean from C to D and find the ratio of that with the known measurement.
ratio = known / Euclidean
Then find the Euclidean between A & B and use the earlier found ratio to convert the Euclidean to actual distance.
distance = euclidean * ratio
euclidean "sqrt((x2-x1)**2+(y2-y1)**2)"

resizing images based on distance between 2 objects in the image

I have multiple images, each image has 2 objects,but the camera capturing those images has been moving forward and backward, I want to resize all the images so that the distance between the 2 objects can be the same in all the images.
Can it be done in python and opencv.
currently I'm trying to get the ratio between the distances of 2 images, and then resize, but I can't get the right answer
code:
resize_factor = default_dist_bet_objects / current_image_distance
res = cv2.resize(image, fx = resize_facor, fy= resize_factor,
interpolation=cv2.INTER_CUBIC)
then i either crop or paste on another image so that all sizes (300,400)

Foggy images detection [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
experts
I am doing a project about analysing the green trends of the trees.
In term of initial processing, I've got intensity value for the whole 500 images and decided the threshold for selecting good images from the datasets. It's around from 60 to 122, and I named the range as good images.
However, the tricky issue was that some of the foggy images were also in that range. The intensity of good images is from 90 to 120, some of the foggy images have the same intensity value compared to the good one.
the intensity of iamges
So far, it's the code for getting the intensity of one image and the average of the intensity for 500 images
im = Image.open('IMAG0087.JPG')
im_grey = im.convert('LA')
width,height = im.size
total=0
for i in range(0,width):
for j in range(0,height):
total += im.getpixel((i,j))[0]
mean = total / (width * height)
print mean
Getting the average of the intensity for 500 images:
results = []
for dirpath, dirnames, filenames in os.walk("/Users/Terrynightbleach/Desktop/Dataset-Tree/No2_Fraser_Gully/"):
for filename in [f for f in filenames if f.endswith('.JPG')]:
img = cv2.imread(filename)
avg_color_per_row = numpy.average(img, axis=0)
avg_color = numpy.average(avg_color_per_row, axis=0)
results.append(sum(avg_color/3))
np_results = np.array(results)
plt.hist(np_results,bins=100)
plt.show()
Are there any other values that I am supposed to use in order to discard those foggy images out from the datasets? And how should I achieve it by python? That would be really helpful if you could show the code.
Thank you so much!!!!!
As you can see your foggy images have very low horizontal variance. Therefore you could compute average horizontal variance for each image. Here's a quick example:
import Image
import glob
def slow_horizontal_variance(im):
'''Return average variance of horizontal lines of a grayscale image'''
width, height = im.size
if not width or not height: return 0
vars = []
pix = im.load()
for y in range(height):
row = [pix[x,y] for x in range(width)]
mean = sum(row)/width
variance = sum([(x-mean)**2 for x in row])/width
vars.append(variance)
return sum(vars)/height
for fn in glob.glob('*.png'):
im = Image.open(fn).convert('L')
var = slow_horizontal_variance(im)
fog = var < 200 # FOG THRESHOLD
print ('%5.0f - %5s - %s' % (var, fog and 'FOGGY' or 'SHARP', fn))
Output:
104 - FOGGY - 00.png
298 - SHARP - 01.png
597 - SHARP - 02.png
130 - FOGGY - 03.png
The images:
00.png
01.png
02.png
03.png
So using numpy, instead of your code:
avg_color_per_row = numpy.average(img, axis=0)
avg_color = numpy.average(avg_color_per_row, axis=0)
You would have something like:
intensity_variance_per_row = numpy.var(img, axis=0)
avg_variance = numpy.average(intensity_variance_per_row, axis=0)
fog = avg_variance < 200 # FOG THRESHOLD
print ('%5.0f - %5s - %s' % (avg_variance, fog and 'FOGGY' or 'SHARP', filename))
(Unfortunately, I'm too lazy to install numpy on this machine, so I cannot confirm it works as well as my slow code above. If it doesn't, you might need to change numpy.var(img, axis=0) to numpy.var(img, axis=1).)

Categories

Resources