Find the correct 2D translation of a subset of coordinates

I have a problem that I want to solve in R with the examples below. I know this must have been resolved many times, but I could not find a solution that works for me in R.

The core of what I want to do is find how to translate a set of 2D coordinates to best fit into another, larger set of two-dimensional coordinates. Imagine, for example, that you have a Polaroid photo of a small part of the starry sky at night, and you want to keep it in such a position that they correspond to the current positions of the stars.

Here's how to generate data similar to my real problem:

# create reference points (the "starry sky")
set.seed(99)
ref_coords = data.frame(x = runif(50,0,100), y = runif(50,0,100))

# generate points take subset of coordinates to serve as points we 
# are looking for ("the Polaroid")
my_coords_final = ref_coords[c(5,12,15,24,31,34,48,49),]

# add a little bit of variation as compared to reference points 
# (data should very similar, but have a little bit of noise)
set.seed(100)
my_coords_final$x = my_coords_final$x+rnorm(8,0,.1)
set.seed(101)
my_coords_final$y = my_coords_final$y+rnorm(8,0,.1)

# create "start values" by, e.g., translating the points we are 
# looking for to start at (0,0)  
my_coords_start =apply(my_coords_final,2,function(x) x-min(x))

# Plot of example data, goal is to find the dotted vector that 
# corresponds to the translation needed
plot(ref_coords, cex = 1.2) # "Starry sky"
points(my_coords_start,pch=20, col = "red") # start position of "Polaroid"
points(my_coords_final,pch=20, col = "blue") # corrected position of "Polaroid"
segments(my_coords_start[1,1],my_coords_start[1,2],
my_coords_final[1,1],my_coords_final[1,2],lty="dotted")

Data construction, as indicated above, should yield: Open points are the starry sky, red dots my Polaroid when I first come out, blue dots when is Polaroid after I manage to mach it to the sky

, , , .. , , .

.

1000 ( , )

10-20 , , .

, !

: , . , , , . ​​ .

, my_coords_final, , my_coords_start, ref_coords.

start positions and reference data

+4
1

, , (. ) optim(), , , , , , , , -, , , ​​ , , ( ):

##  A brute-force approach where min_dist can be used to 
##    ameliorate some random noise:
min_dist <- 5 
win_thresh <- 0
win_thresh_old <- 0
for(i in 1:nrow(ref_coords)) {
  x2 <- my_coords_start[,1]
  y2 <- my_coords_start[,2]
  x1 <- ref_coords[,1] + (x2[1] - ref_coords[i,1])
  y1 <- ref_coords[,2] + (y2[1] - ref_coords[i,2])

  ##  Calculate all pairwise distances between reference and field data:
  dists <- dist( cbind( c(x1, x2), c(y1, y2) ), "euclidean")

  ##  Only take distances for the sampled data:
  dists <- as.matrix(dists)[-1*1:length(x1),]

  ##  Calculate the number of distances within the minimum
  ##    distance threshold minus the diagonal portion:
  win_thresh <- sum(rowSums(dists < min_dist) > 1)  

  ##  If we have more "matches" than our best then calculate a new
  ##    dx and dy:
  if (win_thresh > win_thresh_old) {
    win_thresh_old <- win_thresh
    dx <- (x2[1] - ref_coords[i,1])
    dy <- (y2[1] - ref_coords[i,2])
  }
}

##  Plot estimated correction (your delta x and delta y) calculated
##    from the brute force calculation of shifts:
points(
  x=ref_coords[,1] + dx, 
  y=ref_coords[,2] + dy,
  cex=1.5, col = "red"
)

enter image description here

, -, , , .

+1

All Articles