Home > Enterprise >  Recalculate coordinates for different image size
Recalculate coordinates for different image size

Time:10-06

I have a fix to complete that involves calculating points in an image that have been incorrectly calculated. I have an image and a string of coordinates that mark a region within that image. Some processing has messed up those points so that they are no longer relative to where they should be & I know how to stop that. The images are of cars and the regions highlight front wing, wheel etc.

I am pretty sure I should be able to re calculate the points for the actual image size based on some ratio but after that the maths is eluding me. Can some one either explain the maths or point me at a decent tutorial for it. Thanks.

This is the code I am trying to undo:

if (currentPoints.Count > 0)
{
    result = true;
    float xWidth = 1500f;
    float xHeight = 1500f;
    float ratio = xWidth / source.Width;
    xHeight = source.Height * ratio;
    if (source.LeftExtent > 0 || source.RightExtent > 0)
    {
        if (source.RightExtent > source.LeftExtent)
        {
            result = false;
            xWidth = source.RightExtent - source.LeftExtent;
        }
    }
    if (source.TopExtent > 0 || source.BottomExtent > 0)
    {
       if (source.BottomExtent > source.TopExtent)
       {
           result = false;
           xHeight = source.BottomExtent - source.TopExtent;
       }
    }

    float xRatio = iWidth / xWidth; 
    float yRatio = iHeight / xHeight;
    List<Point> newPoints = new List<Point>();
    foreach (Point cPoint in currentPoints)
    {
        globals.log.Information("Calculating new coordinates for point: {@cPoint}", cPoint);
        double newX = (cPoint.X - source.LeftExtent) * xRatio;
        double newY = (cPoint.Y - source.TopExtent) * yRatio;
        Point newPoint = new Point(newX, newY);
        globals.log.Information(
                                "New Point calculated: {@newPoint} using x =  ({cPoint.X} - {source.LeftExtent}) x {xRatio}, y =  ({cPoint.Y} - {source.TopExtent}) x {yRatio}",
        newPoint, cPoint.X, source.LeftExtent, xRatio, cPoint.Y, source.TopExtent, yRatio);
        newPoints.Add(newPoint);
   }

The image after running through the above looks something like: enter image description here

& my latest attempt to fix is:

public class EntryPoint
    {
        private readonly ILogger<EntryPoint> logger;
        private readonly APIdeconContext context;

        public EntryPoint(ILogger<EntryPoint> logger, APIdeconContext context)
        {
            this.logger = logger;
            this.context = context;
        }

        public void Run(String[] args)
        {
            var images = context.Images.Where(i => i.ModelId == 3).ToList();

            foreach(var image in images)
            {
                var mappings = context.Mappings.Where(m => m.ImageId == image.ImageId).ToList();
                var mappingDims = discoverMappingExtents(mappings);

                foreach(var mapping in mappings)
                {
                    CalcNewPoints(image, mapping, mappingDims);
                }
            }

        }

        private MappingDimension discoverMappingExtents(List<Mapping> mappings)
        {
            double left = double.MaxValue;
            double right = double.MinValue;
            double top = double.MaxValue;
            double bottom = double.MinValue;

            foreach(var mapping in mappings)
            {
                var coords = mapping.CoOrdinates.Split(' ');
                foreach(var pair in coords)
                {
                    var coord = pair.Split(',');
                    double xPos = 0f;
                    double yPos = 0f;
                    double.TryParse(coord[0], out xPos);
                    double.TryParse(coord[1], out yPos);

                    if(xPos < left)
                    {
                        left = xPos;
                    }
                    else if(xPos > right)
                    {
                        right = xPos;
                    }

                    if(yPos < top)
                    {
                        top = yPos;
                    }
                    else if(yPos > bottom)
                    {
                        bottom = yPos;
                    }
                }
            }

            return new MappingDimension{Left = left, Right = right, Top = top, Bottom = bottom};
        }

        private string CalcNewPoints(Image image, Mapping mapping, MappingDimension source)
        {
            var coordBuilder = new StringBuilder();
            var coords = mapping.CoOrdinates.Split(' ');

            double xRatio = source.Width / image.Width;
            double yRatio = source.Height / image.Height;
            foreach(string pair in coords)
            {
                if(pair.Contains(','))
                {
                    string[] coord = pair.Split(',');
                    double xPos = 0f;
                    double yPos = 0f;
                    double.TryParse(coord[0], out xPos);
                    double.TryParse(coord[1], out yPos);

                    double newX = (xPos - source.Left) * xRatio;
                    double newY = (yPos - source.Top) * yRatio;

                   coordBuilder.Append($"{newX},{newY} ");
                }
            }

            return coordBuilder.ToString().Trim();
        }
    }

    public class MappingDimension
    {
        public double Left { get; set; }
        public double Right { get; set; }
        public double Top { get; set; }
        public double Bottom { get; set; }

        public double Width 
        { 
            get
            {
                return Right - Left;
            }
        }
        public double Height 
        { 
            get
            {
                return Bottom - Top;
            }
        }
    }

CodePudding user response:

The code to translate from one range of values to another is

 toMin   ((toMax - toMin) / (fromMax - fromMin)) * (value - fromMin);

I.e. start by subtracting the offset used for the from-range, multiply by the relative scale, and add the to-offset. For images, offset, i.e. fromMin/toMin is zero, unless the images have different positions, and the fromMax/toMax would be the respective image size.

Do the same calculation for x and y coordinates and you can rescale your points.

  • Related