Digital_Utopia
Digital_Utopia

Reputation: 856

Trying to generate a texture for a new UV set from the original UV set and texture, but would like to capture more of the texture to eliminate seams

As I said, I have a mesh that I decided to redo the UVs on, and in order to save time, I've stored the original UVs by face, as well as the new UVs to separate files. The code I have successfully transfers and places the detail from the old texture to the new one, but due to the fact that pixels don't perfectly fit on the edge of a triangle, the result has a lot of seams.

white lines everywhere

I'd be grateful if someone could help by increasing the size of the captured/placed triangle by a couple of pixels to hopefully eliminate these seams:

program.cs:

using System.Drawing;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;

namespace texgen
{
    internal class Program
    {
        static void Main()
        {
            // Paths to the binary files and images
            string originalUVFilePath = @"E:\uvbackup.bin";
            string newUVFilePath = @"E:\uvnewbackup.bin";
            string originalImagePath = @"E:\Ship_Mat_Fed_Galaxy_2019_Type1_D.bmp";
            string newImagePath = @"E:\output_image.bmp";

            // Read and normalize the UVW coordinates
        UVWCoordinates[] originalUVWs = UVWReader.ReadAndNormalizeUVWCoordinates(originalUVFilePath);
        UVWCoordinates[] newUVWs = UVWReader.ReadAndNormalizeUVWCoordinates(newUVFilePath);

        // Load the original image
        Mat originalImage = CvInvoke.Imread(originalImagePath, ImreadModes.Color);

        // Create a new blank image
        Mat newImage = new Mat(originalImage.Size, DepthType.Cv8U, 3);
        newImage.SetTo(new MCvScalar(0));

        // Map the texture
        UVWMapper.MapTexture(originalImage, originalUVWs, newUVWs, newImage);

        // Save the new image
        CvInvoke.Imwrite(newImagePath, newImage);

        Console.WriteLine("Processing done. Check the new image.");
        }
    }
}

UVWReader.cs:

using System.IO;
using System.Collections.Generic;
using System.Numerics;

public struct UVWCoordinates
{
    public int FaceIndex;
    public Vector3 UVW1;
    public Vector3 UVW2;
    public Vector3 UVW3;
}

public class UVWReader
{
    public static UVWCoordinates[] ReadAndNormalizeUVWCoordinates(string filePath)
    {
        var coordinatesList = new List<UVWCoordinates>();

        using (var reader = new BinaryReader(File.Open(filePath, FileMode.Open)))
        {
            while (reader.BaseStream.Position != reader.BaseStream.Length)
            {
                var coord = new UVWCoordinates
                {
                    FaceIndex = reader.ReadInt32(),
                    UVW1 = NormalizeUVW(new Vector3((float)reader.ReadDouble(), (float)reader.ReadDouble(), (float)reader.ReadDouble())),
                    UVW2 = NormalizeUVW(new Vector3((float)reader.ReadDouble(), (float)reader.ReadDouble(), (float)reader.ReadDouble())),
                    UVW3 = NormalizeUVW(new Vector3((float)reader.ReadDouble(), (float)reader.ReadDouble(), (float)reader.ReadDouble()))
                };

                coordinatesList.Add(coord);
            }
        }

        return coordinatesList.ToArray();
    }

    private static Vector3 NormalizeUVW(Vector3 uvw)
    {
        return new Vector3(uvw.X - (float)Math.Floor(uvw.X), uvw.Y - (float)Math.Floor(uvw.Y), uvw.Z);
    }
}

UVWMapper.cs:

using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using System.Numerics;
using System.Drawing;

public class UVWMapper
{
    public static void MapTexture(
        Mat originalImage,
        UVWCoordinates[] originalUVWs,
        UVWCoordinates[] newUVWs,
        Mat newImage)
    {
        for (int i = 0; i < originalUVWs.Length; i++)
        {
            var origUVW = originalUVWs[i];
            var newUVW = newUVWs[i];

            // Define the source points (original UVs)
            PointF[] srcPoints = new PointF[]
            {
                new PointF(origUVW.UVW1.X * originalImage.Width, (1 - origUVW.UVW1.Y) * originalImage.Height),
                new PointF(origUVW.UVW2.X * originalImage.Width, (1 - origUVW.UVW2.Y) * originalImage.Height),
                new PointF(origUVW.UVW3.X * originalImage.Width, (1 - origUVW.UVW3.Y) * originalImage.Height)
            };

            // Define the destination points (new UVs)
            PointF[] dstPoints = new PointF[]
            {
                new PointF(newUVW.UVW1.X * newImage.Width, (1 - newUVW.UVW1.Y) * newImage.Height),
                new PointF(newUVW.UVW2.X * newImage.Width, (1 - newUVW.UVW2.Y) * newImage.Height),
                new PointF(newUVW.UVW3.X * newImage.Width, (1 - newUVW.UVW3.Y) * newImage.Height)
            };

            // Get the transformation matrix
            Mat transformationMatrix = CvInvoke.GetAffineTransform(srcPoints, dstPoints);

            // Extract the triangle from the original image
            Mat originalTriangle = ExtractTriangle(originalImage, srcPoints);

            // Warp the triangle to the new coordinates
            Mat warpedTriangle = new Mat();
            CvInvoke.WarpAffine(originalTriangle, warpedTriangle, transformationMatrix, newImage.Size, Inter.Linear, Warp.Default, BorderType.Constant, new MCvScalar(0));

            // Add the warped triangle to the new image
            CvInvoke.Add(newImage, warpedTriangle, newImage);
        }
    }

    private static Mat ExtractTriangle(Mat image, PointF[] srcPoints)
    {
        // Create a mask for the triangular area
        Mat mask = new Mat(image.Size, DepthType.Cv8U, 1);
        mask.SetTo(new MCvScalar(0));
        VectorOfPoint triangle = new VectorOfPoint(Array.ConvertAll(srcPoints, p => new Point((int)p.X, (int)p.Y)));
        CvInvoke.FillConvexPoly(mask, triangle, new MCvScalar(255));

        // Extract the triangular portion from the image
        Mat triangularPortion = new Mat();
        CvInvoke.BitwiseAnd(image, image, triangularPortion, mask);

        return triangularPortion;
    }
}

Upvotes: 0

Views: 28

Answers (0)

Related Questions