ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • c# mat->float[]->하나로 합친후->libtorch
    개발 히스토리 2023. 3. 25. 22:21

    먼저 기본적인 float으로 만드는 형태.

    using System;
    using OpenCvSharp;
    
    public class ImageProcessor 
    {
        public float[] LoadImage(string imagePath) 
        {
            // 이미지 파일을 그레이스케일로 불러옵니다.
            Mat image = Cv2.ImRead(imagePath, ImreadModes.GrayScale);
    
            // 이미지의 높이, 너비, 채널 수를 가져옵니다.
            int height = image.Rows;
            int width = image.Cols;
            int channels = image.Channels();
    
            // 이미지 데이터를 float 배열로 변환합니다.
            float[] imageData = new float[height * width * channels];
            int idx = 0;
            for (int c = 0; c < channels; c++)
            {
                for (int h = 0; h < height; h++)
                {
                    for (int w = 0; w < width; w++)
                    {
                        // 0 ~ 255 범위의 값을 0 ~ 1 범위로 정규화합니다.
                        imageData[idx++] = (float)image.At<byte>(h, w, c) / 255.0f;
                    }
                }
            }
    
            // 변환된 이미지 데이터를 반환합니다.
            return imageData;
        }
    }

     

     

     

    복수개의 float으로 붙이는 코드. 사실상 난 이걸 쓰진 않는다. 

    using System;
    using System.Linq;
    public class ImageProcessor 
    {
        public float[] LoadImages(string[] imagePaths) 
        {
            // 이미지 파일들을 불러와서 float 배열로 변환합니다.
            float[][] imageDataList = new float[imagePaths.Length][];
            for (int i = 0; i < imagePaths.Length; i++)
            {
                imageDataList[i] = LoadImage(imagePaths[i]);
            }
    
            // 이미지 데이터를 하나의 float 배열로 결합합니다.
            float[] imageData = new float[imageDataList.Sum(arr => arr.Length)];
            int offset = 0;
            foreach (float[] arr in imageDataList)
            {
                arr.CopyTo(imageData, offset);
                offset += arr.Length;
            }
    
            // 변환된 이미지 데이터를 반환합니다.
            return imageData;
        }
    }

     

     

     

    입력 imageData는 여러 이미지를 연결하여 하나의 float[]으로 만들어진다.

    [C, H, W] 차원으로 MAT이 아닌 일반적인 IplImage같은 형태이고, 이걸 멀티 배치로 붙인 것.

    이것을 대상으로 libtorch추론하는 코드는 아래와 같다.

    #include <torch/torch.h>
    void Inference(float* imageData, int batchSize, int channels, int height, int width)
    {
      // 이미지당 필요한 메모리 계산. 근데 이거 어디다 쓰노
      int singleImageSize = channels * height * width;
      int totalImageSize = batchSize * singleImageSize;
      // 이미지 데이터를 Tensor 객체로 변환합니다.
      torch::TensorOptions options(torch::kFloat32);
      torch::Tensor tensor = torch::from_blob(imageData, {batchSize, channels, height, width}, options);
      // Tensor 객체를 이용하여 추론을 수행합니다.
     
      // Run the inference on the input tensor
      torch::Tensor output_tensor = module.forward({imageData}).toTensor();
    
      // Get the predicted classes
      torch::Tensor classes_tensor = torch::argmax(output_tensor, /*dim=*/1);
    
      // Create a probability map for each class
      torch::Tensor softmax_output_tensor = torch::softmax(output_tensor, /*dim=*/1);
      torch::Tensor probability_map_tensor = softmax_output_tensor.select(/*dim=*/1, /*index=*/1);
    
      // Convert the probability map to a segmentation mask
      cv::Mat segmentation_mask(batchSize, height, CV_8UC1);
    
      for (int i = 0; i < batchSize; i++) {
           for (int j = 0; j < height; j++) {
                for (int k = 0; k < width; k++) {
                   float probability = probability_map_tensor[i][j][k].item<float>();
                       int class_id = classes_tensor[i][j][k].item<int>();
       				   segmentation_mask.at<uchar>(i, j, k) = (class_id == 1 && probability > 0.5) ? 255 : 0;
       			}
       		}
      }
      cv::imshow("Segmentation Mask", segmentation_mask);
      cv::waitKey(0);
     }

     

     

     

     

     

     

     

     

     

     

    CSHAR에서 GPU 메모리 올리는 방법.

    문제는...이 구조체를..C++에서 사용할 수 없다는거;;

     

    using ManagedCuda;
    using ManagedCuda.BasicTypes;
    using ManagedCuda.VectorTypes;

    public void CopyFloatArrayToGPU(float[] array)
    {
        // Initialize CUDA context
        CudaContext cuda = new CudaContext();

        // Allocate memory on the GPU
        CudaDeviceVariable<float> gpuArray = new CudaDeviceVariable<float>(array.Length);

        // Copy the array to the GPU memory
        gpuArray.CopyToDevice(array);

        // Free the allocated memory on the GPU
        gpuArray.Dispose();

        // Dispose of the CUDA context
        cuda.Dispose();
    }

     

     

     

     

     

     

     

     

     

     

     

     

     

Designed by Tistory.