I have used this question to help me come up with an undistorted coordinated system of an image. Now, I'm not sure how to implement the new coordinate system into the image so I can be able to produce an undistorted image.
I'm having trouble finding answers that don't involve Matlab, OpenCV, or C++ as I am using R.
The answer I'm using from the cited question has given me the following transformed xy coordinate :
1 -19.50255239, -19.50255239
2 -18.26735544, -18.26735544
3 -17.03391152, -17.03391152
4 -15.80221494, -15.80221494
5 -14.57225998, -14.57225998
6 -13.34404095, -13.34404095
...
and so on for 512 pixels in a 512 x 512 image.
How to apply this back to the original 512 x 512 image is what I'm struggling with. I've seen some mention on pages like the Open CV page here and specific pre-defined shifts, or latitudinal/longitudinal shifts, use SpatialObjectsDataFrames, but not from one user-defined list of xy coordinates to another.
-An example of getting the source image coordinates:
im_coords <- RSAGA::grid.to.xyz(as.matrix(as.raster(im)))
(note, I don't actually want to raster the images, its just what I found at the time)
-Code I'm using to get the transformed coordinates:
undistort <- function(X, Y, a, b, c, d = 1, imWidth = 512, imHeight = 512) {
#radial barrel distortion
normX <- X - (imWidth / 2)
normY <- Y - (imHeight / 2)
#rmax
radius_u <- sqrt(imWidth^2 + imHeight^2)
#normalize r so that its between 0 and 1
r <- sqrt(normX^2 + normY^2) / radius_u
#Barrel distorition equation: where "r" is the destination radius and "Rsrc" is the source pixel to get the pixel color from
Rsrc <- r * (a*r^3 + b*r^2 + c*r + d)
theta <- ifelse(Rsrc == 0, 1, 1 / atan(Rsrc) * Rsrc)
newX <- (imWidth / 2) + theta * normX
newY <- (imHeight / 2) + theta * normY
return(data.frame(X = newX, Y = newY))
}
Here is a sample sample 512x512 .png barrel distorted image: https://imgur.com/a/W9Qz70W
I'm wondering if kriging could be useful? Or gdalwarp or proj4string? Not sure how to implement these.
UPDATE: Using Rohit's suggestions I was able to distort a rainbow grid from:
to this:
When I try it with the barrel image I get this weird superimposed image:
Ok, I think it is down to what coefficients you use as seen here:
You don't actually need to calculate the transformed xy coordinates. You just need the function that takes the x and y coordinates and returns the undistorted ones. Given your undistort
function, write a wrapper around it that uses only x and y as inputs:
im2 <- imwarp(im1, function(x,y){
undistort(x,y,a=1,b=2,c=4) # Give appropriate values for arguments, I'm not an expert.
})
If you want to map specifically from one list to another, then you can do that as well:
df <- expand.grid(x=1:512,y=1:512) # Original grid coordinates
df1 <- undistort(X=df$x,Y=df$y) # Undistorted grid coordinates
im2 <- imwarp(im1, function(x,y){
df1[df$x==x & df$y==y,] # Map appropriately. Should still work.
})
Try out different options for interpolation
to see what works best.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With