🔥 Programming/OpenCV

[OpenCV4] C# OpenCV4 배경색 변경

스쳐가는비 2022. 11. 10. 21:33

배경색 변경

OpenCV4를 사용하다보면, 이미지를 병합시켜야할때와, 병합 이후 배경이 함께나와 제거해야할 경우가 많다.
실시간으로 병합되는 이미지를 배경 이미지 내에서의 위치를 변경시켜야할 때,
그 이미지의 배경을 지워주지 않으면 원활한 이미지 병합을 했다고 볼 수 없다.

배경 자체를 지우는 방법도 있지만, 우선 배경 색 변경을 하는 방법에 대해 알아보자.

변경할 이미지는 배경이 검은색인 볼링공 이미지이다.

해당 이미지의 배경색을 흰색으로 만들 예정이다.

C#에서 포인터를 사용하려면 unsfae를 이용하여야 한다.
그리고 비트맵의 Lock Bits를 통해 Data를 가져오고, Scan0을 통해 포인터 주소를 구한다.
이후 비트맵의 한 픽셀의 RGB 값이 나오게 되는데 이 부분을 수정을 통해 색을 바꿔 보도록 하자.
아래는 결과 이미지이다.

 

Code ( C# )

using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RemoveBackground
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            pictureBox1.Image = ImageProcessing(Properties.Resources.bowling).ToBitmap();
        }

        private Mat ImageProcessing(Bitmap bmp)
        {
            Mat bowling = new Mat();

            Cv2.ImShow("Before", Properties.Resources.bowling.ToMat());

            BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
            
            Color removeTargetColor = Color.Black;
            int changeColor = Color.Transparent.ToArgb();
            double threshold = 100;
            
            unsafe
            {
                int* length = (int*)data.Scan0 + bmp.Height * bmp.Width;
                for (int* p = (int*)data.Scan0; p < length; p++)
                {
                    Color pixelColor = Color.FromArgb(*p);
            
                    double r = Math.Pow((double)(pixelColor.R - removeTargetColor.R), 2.0);
                    double g = Math.Pow((double)(pixelColor.G - removeTargetColor.G), 2.0);
                    double b = Math.Pow((double)(pixelColor.B - removeTargetColor.B), 2.0);
                    double delta = Math.Sqrt(r + g + b);
            
                    if (delta <= threshold)
                        *p = changeColor;
                }

                bmp.UnlockBits(data);
                bowling = bmp.ToMat();
                bmp.Dispose();
            }
            

            return bowling;
        }
    }
}