10년이 훨씬 넘은 구형 데스크탑 PC가 한대 있어 어떻게 처리할까 살펴보다가 SSD 교체로 재사용 해보기로 했습니다. 그 당시 고성능 PC로 i5 3.3GHz에 1TB 7200RPM SATA 3G, GeForce 550Ti가 장착되어 있었고요, 어느때부터 아이들 교육용 PC로 사용하다가 HDD가 오래되다보니 버벅거리는 상태가 되었네요. 하드디스크 HDD 교체와 램 RAM 만 추가해주면 기본적인 영상처리 알고리즘 구현 및 프로그래밍 정도는 가능할 수 있어 보였습니다. 그래서 PC 리뉴얼을 위해 제가 확인하고 진행한 과정은 아래와 같습니다. 

 

( 글 순서 )

1. 윈도우 드라이브 마이그레이션

2. 윈도우 제품 키 확인 + PC 청소

3. 윈도우 설치 USB 만들기 + 윈도우 설치

 

위 세 과정을 진행하면서 중간중간 시간을 허비한 부분이 있어, 도움 될 만한 부분이 있으면 참고하셨으면 좋겠습니다.

 

1. 윈도우 C: 드라이브 마이그레이션

 

SSD 교체 시 여러 방법들을 찾아보던 중에 드라이브 마이그레이션 방법을 알게 되어서 시도를 했습니다. 윈도우 설치 파일을 만들 필요도 없고 윈도우 제품키도 필요 없으니 이거다 싶었죠. 내장형 SSD 하나를 구매하고 마이그레이션 툴들을 검색해보니 여러 종류가 있는데 유료와 무료로 나뉩니다. 무료라고 하는 툴들도 정책이 바뀌었는지 진행하다보면 비용 지불 팝업이 뜨네요. 제가 사용해 본 툴은 매크리움 리플렉트 Macrium Reflect 툴이고요, 현 시점 30일 무료로 사용할 수 있습니다.

 

https://www.macrium.com/reflectfree?mo

 

위 사이트에 들어가면 Home User > Reflect X Home Free Trial로 설치하면 됩니다. 툴 사용법은 여러 블로그들에 설명이 잘 되있고요, HDD 전체 드라이브를 SDD 전체 드라이브로 마이그레이션 하는 방법과 실제 OS로 사용하는 C: 드라이브만 선택적으로 마이그레이션 할 수 있습니다. 주의할 점은 전체를 하든 일부 파티션만 하든 각 용량과 같거나 커야 합니다. 예를 들어 HDD 전체가 500G라면 SDD도 500G 이상으로 준비하면 됩니다.

 

제 경우 OS로 사용하는 C: 드라이브만 마이그레이션을 시도 했었고요, 결론적으로는 실패했습니다. 이유는 오랜기간 HDD를 사용하다보니 배드섹터 Bad Sector가 많아 마이그레이션 오류가 문제 였습니다. 디스크 정리를 하면 된다고 하는데 OS 드라이브다보니 문제가 될 수 있어 포기하고 깨끗하게 새로 설치하기로 했습니다.

 

2. 윈도우 Window 제품키 확인

 

윈도우를 새로 설치하게 되면 기존 제품키를 알고 있거나 구매를 해야하는데 우선 현재 윈도우 버전과 제품키를 확인했습니다. 구형 PC가 모 브랜드 PC여서 본체에 제품키를 확인할 수 있었습니다. 그런데 최초 윈도우7에서 중간에 윈도우 10으로 업그레이드를 해서 제품키를 한번더 확인해 봤고요, 윈도우 키 확인 방법들도 여러가지 있는데 아래 두가지로 확인해 봤습니다.

 

( 윈도우키 확인 방법 )

1) wmic path softwarelicensingservice get Oa3xOriginalProductKey

2) reg query “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform” /v BackupProductKeyDefault

 

명령 프롬프트 cmd 창을 열어서 위 둘 중에 하나를 넣어 주시면 됩니다. 제 PC의 경우 2)번으로 시리얼키 25자리 확인할 수 있었습니다. 최초 윈도우7일때 키와 윈도우10으로 업그레이드 되면서 윈도우 키도 바뀐걸 알 수 있었고, 윈도우 구매 없이 설치 진행해 갈 수 있었습니다.

 

PC 청소 및 윈도우 설치 과정은 다음 블로그에서 확인할 수 있습니다. 

윈폼 환경에서 개발을 하다 보면 여러개의 SubForm 생성이 필요한 경우 가 빈번합니다. 첫 번째 예에서는 한장의 이미지를 Main에서 Sub로 전달하는 방법입니다. 예에서는 이미지를 읽어 와서 전달하는 예이지만 메모리에 저장되어 있는 Bitmap 등의 이미지도 동일한 방법으로 전달이 가능합니다. 예에서는 SubForm에 PictureBox가 이미 추가 되어 있다고 가정합니다.

 

1) 이미지 한장 전달 시, 서브폼 SubForm 및 메인폼 MainForm

using System;
using System.Drawing;
using System.Windows.Forms;

// sub form
public partial class SubForm : Form
{
    public SubForm(Image image)
    {
        InitializeComponent();
        if (image != null)
        {
            pictureBox1.Image = image; // picture box
        }
    }
}

 

using System;
using System.Drawing;
using System.Windows.Forms;

// main form
public partial class MainForm : Form
{
    private Image lenaImage;

    public MainForm()
    {
        InitializeComponent();
        lenaImage = Image.FromFile("Lena.jpg");  // 로컬 이미지 로드
    }

    private void btnOpenSubForm_Click(object sender, EventArgs e) // 버튼
    {
        SubForm subForm = new SubForm(lenaImage);
        subForm.Show();
    }
}

 

필요따라 여러 장의 이미지를 전달할 경우도 있습니다. 두번째 예에서는 리스트 List를 이용하여 여러 이미지를 전달하는 방법입니다. 이미지 뿐만 아니라 다른 형 Type에 여러 데이터를 전달 할때에는 ArrayList를 활용하면 쉽게 전달 할 수 있습니다.

 

2) 이미지 여러장 전달 시, 서브폼 SubForm 및 메인폼 MainForm

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

// sub form
public partial class SubForm : Form
{
    public SubForm(List<Image> images)
    {
        InitializeComponent();
        
        if (images != null && images.Count > 0)
        {
           // 여러 Picture Box에 각 이미지 표시
            pictureBox1.Image = images[0];
            pictureBox2.Image = images[1];
            pictureBox3.Image = images[2];
            
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

// main form
public partial class MainForm : Form
{
    private List<Image> imageList = new List<Image>();

    public MainForm()
    {
        InitializeComponent();

        // 예시: 이미지 여러 개 로드
        imageList.Add(Image.FromFile("A.jpg"));
        imageList.Add(Image.FromFile("B.jpg"));
        imageList.Add(Image.FromFile("C.jpg"));
    }

    private void btnOpenSubForm_Click(object sender, EventArgs e)
    {
        SubForm subForm = new SubForm(imageList);
        subForm.Show();
    }
}

프로그래밍을 하다보면 두 개의 집합 사이 관계를 계산해야 될 때가 많습니다. 아래는 DataTable의 활용 시에 두 개의 Table 사이에 차집합을 구하는 LINQ를 활용한 두 가지 예입니다. 비교적 간단하거나 짧은 행의 Table에 적용하면 유용하며, 또한 처리 시간에 구애받지 않는다면 유용할 수 있습니다. 큰 Table들이면서 실시간 처리가 목적이라면 어렵지 않을까 합니다.

 

첫 번째 예제에서는 AsEnumerable().Where()와 Any()문을 활용하여 특정 행을 비교하여 차집합을 구하는 방식입니다. 두 번째 예에서는 AsEnumerable().Except()와 DataRowComparer.Default를 이용한 방식 입니다.

 

예제 #1. AsEnumerable().Where() 사용 예

using System;
using System.Data;
using System.Linq;

class Program
{
    static void Main()
    {
        // 첫 번째 DataTable 생성 및 데이터 추가
        DataTable dt1 = new DataTable();
        dt1.Columns.Add("Num", typeof(int));
        dt1.Columns.Add("Tag", typeof(string));

        dt1.Rows.Add(1, "A");
        dt1.Rows.Add(2, "B");
        dt1.Rows.Add(3, "C");

        // 두 번째 DataTable 생성 및 데이터 추가
        DataTable dt2 = new DataTable();
        dt2.Columns.Add("Num", typeof(int));
        dt2.Columns.Add("Tag", typeof(string));

        dt2.Rows.Add(2, "B");
        dt2.Rows.Add(3, "C");

        // 차집합: dt1에는 있고 dt2에는 없는 행
        var difference = dt1.AsEnumerable()
            .Where(row1 => !dt2.AsEnumerable().Any(row2 =>
                row1.Field<int>("Num") == row2.Field<int>("Num") &&
                row1.Field<string>("Tag") == row2.Field<string>("Tag")));

        // 결과 출력
        Console.WriteLine("차집합 결과 (dt1 - dt2):");
        foreach (var row in difference)
        {
            Console.WriteLine($"ID: {row["Num"]}, Name: {row["Tag"]}");
        }
    }
}

 

예제 #2. AsEnumerable().Except() 사용 예

using System;
using System.Data;
using System.Linq;

class Program
{
    static void Main()
    {
        // 첫 번째 DataTable 생성
        DataTable dt1 = new DataTable();
        dt1.Columns.Add("Num", typeof(int));
        dt1.Columns.Add("Tag", typeof(string));

        dt1.Rows.Add(1, "A");
        dt1.Rows.Add(2, "B");
        dt1.Rows.Add(3, "C");

        // 두 번째 DataTable 생성
        DataTable dt2 = new DataTable();
        dt2.Columns.Add("Num", typeof(int));
        dt2.Columns.Add("Tag", typeof(string));

        dt2.Rows.Add(2, "B");
        dt2.Rows.Add(3, "C");

        // 차집합 구하기
        var difference = dt1.AsEnumerable()
                            .Except(dt2.AsEnumerable(), DataRowComparer.Default);

        // 결과 출력
        DataTable resultTable = difference.CopyToDataTable();
        Console.WriteLine("차집합 결과:");
        foreach (DataRow row in resultTable.Rows)
        {
            Console.WriteLine($"{row["Num"]}, {row["Tag"]}");
        }
    }
}

 

Affine Transform 어파인 변환 (또는 아핀 변환)은 컴퓨터 비젼과 로봇, 그래픽스 등에서 사용하는 좌표 변환 기술 입니다. 일반적인 영상처리에서는 그 좌표점에 Intensity를 다뤘다면 기하학 변환에서는 좌표의 변경을 통해 물체의 위치, 크기, 기울기, 방향 등을 변환하는 기법으로 볼 수 있습니다.

 

선형 변환과 이동을 조합하여 2차원 또는 3차원 변환을 할 수 있어 수학적으로는 선형 대수 Linear Algebra와 밀접합니다. 간략하게 정의를 보게 되면, 변환된 좌표 (x’, y’)는 원래 좌표 (x, y)에 대해 다음과 같이 표현할 수 있습니다.

 

[ x'; y'] = [a b; c d][x; y] + [e; f]

여기서 [a b; c d] : 선형 변환 행렬, [e; f]: 이동 벡터

 

위 변환을 동차 좌표 homogeneous coordinates로 바꾸면 아래의 같이 하나의 행렬곱으로 표현 가능합니다.

 

[x'; y'; 1] = [a b e; c d f; 0 0 1][x; y; 1]

 

동차 좌표계 Homogeneus coordinates 는 우리가 일반적으로 사용하는 카르테시안 좌표계와 달리 추가적인 차원을 포함하여 변환을 쉽게 수행할 수 있습니다. 특히 Affine Transform과 Projective Transform 같은 변환을 하나의 행렬 연산으로 통합하기 위해 사용됩니다.

 

선형 변환 행렬은 변환 종류에 따라 아래와 같습니다. 이동 Translation은 이동 벡터에 따른 위치 변환이며, 이 외 변환은 중심에 변화가 없는 선형 변환으로 볼 수 있습니다. Affine Transform의 주요 특징은 1) 변환 후에도 직선은 그대로 직선인 직선성 유지, 2) 평행한 선은 변환 후에도 평행 유지, 3) 확대 및 축소 시 모양 유지, 4) 변환 후에도 역변환 가능 정도로 요약할 수 있습니다. 기하학 변환은 실무에서 이미지 왜곡 보정, 물체 추적, 이미지 파노라마, 카메라 켈리브레이션, 증강 현실 등에 활용되며 3D 게임에 기본 이론으로도 볼 수 있습니다.

 

Translation (이동 변환) 위치를 이동
Scaling (크기 변환) 크기를 조절
Rotation (회전 변환) 축을 중심으로 회전
Shearing (기울임 변환) 평행 형태 기울임 변형
Reflection (반사) 대칭 이동  

 

아래는 Affine Transform 중 이미지 위치 변환에 대한 Python, Matlab, C# 코드 활용 예입니다. 파이썬에서는 warpAffine 함수를 사용할 수 있으며, 매트랩에서는 affine2d와 imwarp을 활용 할 수 있습니다. C와 C#에서는 OpenCV를 활용하여 쉽게 테스트 해 볼 수 있습니다.

 

import cv2
import numpy as np
# 이미지 로드
image = cv2.imread("lena.jpg")
# 변환 행렬 생성 (x축 50px 이동, y축 30px 이동)
M = np.float32([[1, 0, 50], [0, 1, 30]])
# Affine 변환 적용
transformed_image = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
# 결과 출력
cv2.imshow("Original Image", image)
cv2.imshow("Affine Transformed Image", transformed_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
% 이미지 로드
image = imread('lena.jpg');
% Affine 변환 행렬 생성
T = affine2d([1 0 0; 0 1 0; 50 30 1]); % x축 50px, y축 30px 이동
% Affine 변환 적용
transformed_image = imwarp(image, T);
% 결과 출력
subplot(1,2,1), imshow(image), title('Original Image');
subplot(1,2,2), imshow(transformed_image), title('Affine Transformed Image');
using OpenCvSharp;
class Program
{
    static void Main()
    {
        // 이미지 로드
        Mat image = Cv2.ImRead("image.jpg", ImreadModes.Color);
        // 변환 행렬 생성 (x축 50px 이동, y축 30px 이동)
        Mat affineMatrix = new Mat(2, 3, MatType.CV_32F, new float[] { 1, 0, 50, 0, 1, 30 });
        // Affine 변환 적용
        Mat transformedImage = new Mat();
        Cv2.WarpAffine(image, transformedImage, affineMatrix, new Size(image.Width, image.Height));
        // 결과 출력
        Cv2.ImShow("Original Image", image);
        Cv2.ImShow("Affine Transformed Image", transformedImage);
        Cv2.WaitKey(0);
    }
}

When using deep learning in Python, setting up the GPU and CUDA environment is important. There are two main ways to do this:

 

● Personal use – You can install the latest CUDA and PyTorch versions that work best with your GPU.

Work – You may need to use a specific version of PyTorch to match project requirements.

 

To make sure everything runs smoothly, your GPU driver, CUDA, cuDNN, and PyTorch versions must be compatible. Since reinstalling or rolling back versions can take a lot of time, it’s best to set up the environment correctly from the start and focus on actual development.

 

This blog explains how to set up the environment based on PyTorch 1.13, assuming your GPU meets the requirements.

 

1. Checking GPU Environment: Run ‘cmd’ and execute ‘nvidia-smi’ to check the GPU status

Verify the installed CUDA and driver versions. The CUDA version displayed in the command prompt represents the highest supported version, but older versions are also compatible. As of April 2025, the latest driver update for RTX 30 series GPUs includes CUDA 12.x and driver 5xx.xx. Visit the official website below to check for the latest updates and install them accordingly.

 

NVIDIA Driver: docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#cuda-major-component-versions

 

 

2. Checking CUDA Version for PyTorch 1.13

PyTorch can be installed using either conda or pip, and you should set up the CUDA environment based on your personal system before proceeding with the installation. In this step, we are only checking the CUDA version. PyTorch 1.13 is confirmed to be compatible with CUDA 11.6x and 11.7x.

 

pytorch.org/get-started/previous-versions/

 

3. Capability Based on GPU Environment

Additionally, you need to check the Capabilityof your specific GPU. For RTX 3050, 3060, 3070, 3080, and 3090, the capability is 8.6 and they can be used with CUDA 11.1 or later.

 

GPU Capability: en.wikipedia.org/wiki/CUDA

 

4. Setting Up the CUDA Environment and Installing PyTorch

Based on PyTorch 1.13, install CUDA 11.7.x, followed by cuDNN 11.x, considering the GPU capability. For cuDNN, extract the files and copy them into the folder where CUDA is installed to complete the environment setup. Finally, install PyTorch 1.13 using either pipor conda, as previously explained.

 

CUDA: developer.nvidia.com/cuda-toolkit-archive

cuDNN: developer.nvidia.com/rdp/cudnn-archive

 

5. Checking Environment Setup and Functionality: nvcc - - version

You can verify the installation by running "nvcc --version" (or "nvcc -V") in the command prompt “cmd”. The following code can be used to check whether the GPU is available. 

import torch
print(torch.cuda.is_available())


Additionally, in practical applications, the code below can be used to automatically assign the device.

device = torch.device('cuda:0') if torch.cuda.is_available() else torch.device('cpu')

 

** Refer to korean version

파이썬 Python 기반에 Deep Learning(D/L) 활용 시 GPU 및 CUDA 환경 설정에 대한 설명입니다. 환경 설정에 방향은 두 가지 정도로 나뉠 수 있습니다. 개인적인 활용에서는 GPU 환경에 맞춰 CUDA 및 Pytorch 최신 환경으로 구성할 수 있고, 업무 환경 상 Pytorch 특정 버전에 맞춰 환경을 구성해야 될 수도 있겠습니다.

 

환경 설정에서는 GPU 드라이버, CUDA, cuDNN, Pytorch 버전이 호환되어야 정상 활용 가능하므로 개인적인 환경에 따라 다를 수 있겠지만 상황에 따라 재설치 및 Rollback 시간이 상당하므로 가능하면 환경설정에 시간 소모를 줄이고 개발에 집중하는 것이 좋다고 생각합니다.

 

현 블로그에서는 기본적으로 GPU 환경 조건이 충분하다는 상황에서 Pytorch 1.13 기준에서 환경 설정 과정을 설명합니다.

 

1. GPU 환경 확인: cmd 실행 후 ‘nvidia-smi’ 확인, 드라이버 업데이트

CUDA 버전과 드라이버 버전 확인 합니다. cmd 창에 출력되는 CUDA 버전은 지원 가능한 버전이므로 이하 버전들도 적용 가능합니다. 23년 12월 기준 RTX 30 시리즈 드라이버 최신 업데이트 시 CUDA 12.x와 드라이버 5xx.xx 입니다. 아래 주소 확인 후 최신 업데이트 합니다.

 

NVIDIA Driver: docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#cuda-major-component-versions

 

 

 

2. Pytorch 1.13 기준 CUDA 버전 확인

파이토치 설치 방법은 conda와 pip으로 구분되어 있으며 개인 환경에 맞춰 CUDA 환경 구성 후 설치하면 됩니다. 현 시점에서는 CUDA 버전만 확인합니다. 파이토치 1.13은 CUDA 11.6x와 11.7x와 연동되는 것을 확인 할 수 있습니다.

 

pytorch.org/get-started/previous-versions/

 

 

3. GPU 환경에 따른 Capability

추가로 본인 GPU 환경에 따른 Capability를 확인해야 됩니다. RTX 3050/30603070/3080/3090의 경우 Capability 8.6 이며, 이는 CUDA 11.1 이상에서 활용 가능함을 확인 할 수 있습니다.

 

GPU Capability: en.wikipedia.org/wiki/CUDA

 

 

 

4. CUDA 환경 구축 및 Pytorch 설치

파이토치 1.13 호환성 기준으로 Capability 고려하여 CUDA 11.7.x 설치 후 cuDNN 11.x 설치하면 됩니다. cuDNN의 경우 압축 해제 후 파일들을 CUDA 설치된 폴더에 복사/붙여넣기하여 환경 구성을 완료합니다. 이후 앞에서 확인한 파이토치 1.13을 pip 또는 conda로 최종 설치합니다.

 

CUDA: developer.nvidia.com/cuda-toolkit-archive

cuDNN: developer.nvidia.com/rdp/cudnn-archive

 

 

 

5. 환경 구성 및 동작 확인: nvcc - -version

cmd 창에서 ‘nvcc –V’ 또는 ‘nvcc –version’으로 설치 확인 할 수 있습니다. 아래 코드를 통해 GPU 사용 및 할당 가능한지 확인할 수 있습니다.

 

import torch

print(torch.cuda.is_available()) # True면 활용 가능

 

추가로 실무에서 아래 코드로 디바이스 자동 지정 할 수 있습니다.

device = torch.device('cuda:0') if torch.cuda.is_available() else torch.device('cpu')

칼라 분석 처리 목적에 따라 RGB 공간에서 다른 공간으로 변환할 있습니다. OpenCV에서 cvtColor 함수를 사용할 있으며 RGB 공간에서 변환할 경우에는 채널의 순서를 명시적으로 지정해야 합니다. OpenCV 기본 형식은 RGB라고 하는 경우가 많지만 실제로는 BGR입니다. 24비트 이미지의 번째 바이트는 8비트 Blue 성분이고 번째 바이트는 Green, 번째 바이트는 Red 됩니다.

 

아래는 C언어와 Python 활용 따른 예이며 src는 원본, dst는 결과입니다. cvtColor 함수를 활용하면 간단히 색 공간변환을 할 수 있습니다.

 

(C언어): cvtColor(src, dst, cv::COLOR_RGB2GRAY);

(Python): dst = cv.cvtColor(src, cv.COLOR_RGB2GRAY)

 

Luv 같은 비선형 변환은 입력 RGB 영상을 적절한 범위로 정규화하여 처리해야 합니다. 예를 들어 8비트 영상에서 직접 변환된 32비트 부동소수점 영상이 있으면 함수에서 가정하는 0.1 아니라 0.255 범위를 갖게 됩니다. 따라서 cvtColor 호출하기 전에 아래 예와 같이 먼저 영상을 축소해야 합니다.

 

src *= 1./255;

cvtColor(src, dst, COLOR_BGR2Luv);

 

아래는 RGB 공간에서 수식적 변환 관계(Gray, HSV, HLS, Lab)이며  cvtColor의 변환 코드 선택으로 간편히 변환할 수 있습니다. cv::COLOR_RGB2HSV (또는 cv::COLOR_BGR2HSV) 등.

RGB to GRAY 변환

RGB to Gray: Y = 0.299⋅R+0.587⋅G+0.114⋅B

 

RGB to HSV 변환 (Hue, Saturation, Value)

R, G, B 부동 소수점 형식으로 변환하여 [0~1] 범위에 맞게 스케일링 계산 적용합니다.

 

RGB to HLS 변환 (Hue, Luminance, Saturation)

R, G, B 부동 소수점 형식으로 변환하여 [0~1] 범위에 맞게 스케일링  계산 적용합니다.

 

RGB to Lab 변환

R, G, B 부동 소수점 형식으로 변환하여 [0~1] 범위에 맞게 스케일링  계산 적용합니다.

(docs.opencv.org 참조)

인간의 시각 시스템 The Human Visual System은 가시광선(400nm~700nm) 영역에서 수십만 가지의 색상을 구별 할 수 있지만 회색 음영 변화의 경우 약 100가지 정도를 구별할 수 있습니다. 색상 정보 Color Information도 이미지에 다양하게 포함 될 수 있기 때문에 색상 정보에 기반하여 객체 식별 및 추출 등과 같은 이미지 분석에 활용할 수 있습니다.

 

그레이 이미지 Gray Image는 무채색으로 레벨의 크기 Intensity로 표현되므로 에너지에 의한 물리적 양으로 볼 수 있습니다. 반면 밝기 Brightness 와 휘도 Luminance는 색의 인식적 지각에 의해 결정되므로 심리적 특성에 가깝습니다. 예를 들어 파란색과 초록색이 동일하게 강렬한 경우 파란색은 초록색보다 훨씬 더 어둡게 인식됩니다. 색상은 주로 물체의 반사율 특성에 따라 달라지며 빨간색과 초록색을 모두 반사하는 물체는 녹색이지만 빛을 비추는 빨간색이 없을 때 초록색으로 보이고 반대로 녹색이 없을 때는 빨간색으로 보입니다.

 

색상 모델 Color Model은 3D 좌표계로 표현되며 특정 모델 내에서 구성 가능한 모든 색상을 정의하고 특정 색상을 지정할 수 있도록 합니다. 이미지 분석과 처리를 위한 색상 모델들에는 RGB, CMY, HSI, YIQ, HSV, Lab 등 다양합니다. 현 블로그에서는 일반적인 RGB 외 몇 모델을 살펴 보겠습니다. OpenCV 활용 부분에 색상 모델 좌표 변환 설명을 추가하니 참고해 보면 좋겠습니다.

 

RGB Model

그림에서 같이 직각 좌표계로 표현되는 RGB 모델은 Red, Green, Blue의 3개의 축으로 구성됩니다. 회색 Gray은 검정색 Black과 흰색 White을 잇는 선으로 Spectrum이 표현됩니다. RGB 모델은 실생활에 많이 활용되며 칼라 모니터와 대부분의 비디오 카메라에 사용됩니다.

CMY Model

CMY 모델은 Cyan, Magenta, Yellow를 축으로 하는 색상 모델로, RGB 모델의 경우 특정 색상을 얻기 위해 검정색에 무엇을 추가하는 가산 혼합 Additive Model인 반면 CMY는 흰색에서 무엇을 빼는 Subtractive Model 입니다. 주로 칼라 프린터 및 인쇄물에 사용됩니다. 아래 그림은 색상 인식에 대한 Tristimulus Theory로 좌측은 RGB, 우측은 CMY Model을 나타냅니다.

 

HSI Model

HSI 모델은 Hue 색상, Saturation 채도, 크기(세기) Intensity의 3가지 축에 의해 색상을 정의할 수 있습니다. 그림은 HSI의 색상 입체 공간을 나타내며, Red/Green/Blue는 [0,1]범위로 정규화 됩니다. Hue는 0~360도의 각도, Saturation은 0~1, Intensity는 0(Black)~1(White)로 설정할 수 있으며 RGB 모델 간 변환 관계는 아래와 같습니다.

(homepages.inf.ed.ac.uk 참조)

(docs.opencv.org 참조)

영상처리의 가장 기본이 되는 연산 중에는 픽셀 Pixel 연산과 마스크 Mask 연산이 있습니다. 현 블로그에서는 픽셀 간 산술 연산 Arithmetic Operation과 그 응용인 이미지 혼합 Image Blending을 간략히 다루겠습니다. 아래 예에서는 파이썬 코드로 설명하지만 당연히 C언어 함수로도 제공됩니다.

 

이미지 덧셈 Image Addition

덧셈 함수는 cv.add(input1, input2)로 사용할 수 있으며, input1과 input2는 모두 깊이 depth와 유형이 동일해야 하거나 input2는 스칼라 scalar 일 수 있습니다. 아래 예에서 같이 Numpy 연산으로도 이미지 덧셈 연산을 할 수 있습니다. 다만 결과에서 같이 OpenCV 연산은 포화 Saturation 연산이며 Numpy는 modulo 연산이라는 점에 주의해야 합니다.

 

CV 연산과 Numpy 연산 예)

x = np.uint8([250])

y = np.uint8([10])

z1 = cv.add(x,y) # 250+10 = 260 => 255

z2 = x+y                # 250+10 = 260 % 256 = 4

 

이미지 뺄셈, 곱셈, 나눗셈도 각 cv.substract, cv.multiply, cv.divide로 제공되며 형식은 덧셈 연산과 동일합니다.

 

이미지 혼합 Image Blending

이미지 간 혼합감이나 투명감을 주기 위해 이미지 별 다른 가중치를 부여할 수 있습니다. 단순 연산에 응용으로 Result = (1−α)Image1 + αImage2 처럼 가중치를 다르게 적용하여 두 개의 이미지를 혼합 할 있습니다. OpenCV에서는 cv.addWeighted 함수로 제공되며 두 개의 가중치 α, β와 하나의 offset γ을 활용하여 처리할 수 있습니다. 두 개의 가중치의 합은 항상 1이 되어야 합니다. 그림에서는 로봇에 0.7의 가중치를 OpenCV 로고 이미지에 0.3의 가중치로 혼합한 결과 입니다.

 

result =α⋅img1+β⋅img2+γ

result = cv.addWeighted(img1, α, img2, β, γ)

 

 

이미지 논리 연산 Logical Operations

논리 연산자에는 AND, OR, XOR, NOT 가 있습니다. 논리 연산은 이진 Binary 이미지에 적용되며 픽셀 단위로 수행됩니다. 이진 이미지 처리 시 마스킹, 특정 처리, 형태 분석 등 활용될 수 있습니다. 그림에서 같이 AND의 경우 두 입력이 모두 1일 때 1이 되며, OR 연산은 두 입력 모두 또는 하나가 1일 때 1이 됩니다.

 

 

NOT 연산 cv. bitwise_not() 함수를 이용하며 Result = -Input과 같이 입력에 대한 반전과 같습니다. AND 연산은 아래와 같이 활용할 수 있으며 OR 및 XOR도 각 cv.bitwise_or(), cv.bitwise_xor()로 테스트 해 볼 수 있습니다. Input1과 Input2는 모두 동일한 배열이거나 또는 Input1은 배열, Input2는 Scalar가 될 수 있습니다.

                    

AND 연산 파이썬 예)

Result = cv.bitwise_and(Input1, Input2)

프로그래밍을 할 수 있는 언어는 크게 인터프리터 Interpreter와 컴파일 Complile 언어로 구분할 수 있습니다. 앞에서 설명한 C-언어가 컴파일 언어의 대표 예입니다. 인터프리터 언어에는 요즘 많이 활용 중인 파이썬 Python과 매트랩 Matlab 언어가 있습니다.

 

매트랩 Matlab은 수치 컴퓨팅, 데이터 분석 및 시각화에 활발히 사용 됩니다. 인터프리터 언어 특성상 사용하기 쉽고 다양한 소프트웨어 패키지를 이용하여 물리, 수학, 금융 및 제어 시스템을 포함한 다양한 과학 및 엔지니어링 분야에서 널리 사용됩니다. 그러나 파이썬은 무료에 반해 매트랩은 유료로 사용할 수 있습니다.

 

파이썬 Python의 경우 인공지능 분야 활용 확대로 활용성이 급격히 상승한 언어 중에 하나이며 다양한 응용 분야에서 활용되고 있습니다. 웹 Web 개발, Deep Learning(D/L), 네트웍, 서버, 게임, GUI 등등. 다만 무료 사용은 장점이지만 파이썬 버전에 따른 활용에 주의할 필요도 있습니다.

 

넘피 NumPy, 판다스 Pandas, Matplotlib, scikit-learn 등의 라이브러리는 다양한 데이터 분석에 활용 됩니다. 장고 Django와 플라스크 Flask와 같은 프레임워크는 확장 가능한 웹 응용 프로그램을 쉽게 개발할 수 있으며, 인공지능 Artificial Intelligence 과 자연어 처리  Natural Language Processing  분야에서는 텐서플로우 TensorFlow와 파이토치 PyTorch와 같은 프레임워크를 활용하여 훈련하는데 사용됩니다.

 

SciPy와 SymPy와 같은 라이브러리는 과학적 컴퓨팅, 수학적 문제 해결, 시뮬레이션 수행을 위한 도구들을 제공합니다. Pygame 라이브러리는 간단한 비디오 게임을 작성하기 위한 모듈을 제공합니다.

 

파이썬은 그래픽 사용자 인터페이스(GUI) 개발하는 데 사용될 수 있으며, Tkinter, PyQt 및 Kivy와 같은 라이브러리는 Desktop Application을 쉽게 구축할 수 있습니다.

+ Recent posts