상위 목록: 하위 목록: 작성 날짜: 읽는 데 26 분 소요

적분(Integral)

이미지의 적분 값을 계산하여 특정 영역에 대한 합계, 평균, 표준 편차등을 계산할 수 있습니다.

원본(Source, src)은 영상이나 이미지를 사용합니다.



메인 코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace Project
{
    class OpenCV : IDisposable
    {
        IplImage gray;    
        IplImage integral;

        public IplImage GrayScale(IplImage src)
        {
            gray = new IplImage(src.Size, BitDepth.U8, 1);
            Cv.CvtColor(src, gray, ColorConversion.BgrToGray);
            return gray;
        }
        
        public IplImage IntegralImage(IplImage src)
        {
            integral = new IplImage(src.Size, BitDepth.F64, 1);
            integral = this.GrayScale(src);

            IplImage sum = new IplImage(new CvSize(src.Width + 1, src.Height + 1), BitDepth.F64, 1);
            IplImage sqsum = new IplImage(new CvSize(src.Width + 1, src.Height + 1), BitDepth.F64, 1);
            IplImage tiltedsum = new IplImage(new CvSize(src.Width + 1, src.Height + 1), BitDepth.F64, 1);
                    
            Cv.Integral(integral, sum, sqsum, tiltedSum);

            CvMat src_mat = new CvMat(integral.Height, integral.Width, MatrixType.F64C1);
            CvMat sum_mat = new CvMat(sum.Height, sum.Width, MatrixType.F64C1);

            for (int i = 0; i < integral.Width; i++)
            {
                for (int j = 0; j < integral.Height; j++)
                {
                    src_mat[j, i] = integral[j, i].Val0;
                }
            }

            for (int i = 0; i < sum.Width; i++)
            {
                for (int j = 0; j < sum.Height; j++)
                {
                    sum_mat[j, i] = sum[j, i].Val0;
                }
            }

            Console.WriteLine(src_mat);
            Console.WriteLine(sum_mat);

            return sum;
        }
        
        public void Dispose()
        {
            if (gray!= null) Cv.ReleaseImage(gray);   
            if (integral != null) Cv.ReleaseImage(integral);  
        }
    }
}


세부 코드

integral = new IplImage(src.Size, BitDepth.F64, 1);
integral = this.GrayScale(src);

계산 이미지로 사용할 integral을 생성하고 정밀도F32 또는 F64단일 채널 형식만 사용이 가능합니다.

단일 채널로 변경하기 위해 그레이스케일을 적용합니다.


IplImage sum = new IplImage(new CvSize(src.Width + 1, src.Height + 1), BitDepth.F64, 1);
IplImage sqsum = new IplImage(new CvSize(src.Width + 1, src.Height + 1), BitDepth.F64, 1);
IplImage tiltedsum = new IplImage(new CvSize(src.Width + 1, src.Height + 1), BitDepth.F64, 1);

결과 이미지sum, sqsum, tiltedsum을 생성합니다.

이미지 크기너비+1, 높이+1을 사용하며, 정밀도F32 또는 F64단일 채널 형식만 사용이 가능합니다.


sum적분 이미지를 의미합니다.

sqsum제곱된 적분 이미지를 의미합니다.

tiltedsum45° 기울어진 적분 이미지를 의미합니다.


위와 같은 이미지를 입력한다면, 각 픽셀들의 값은 다음과 같습니다.


검은색 픽셀의 값은 0을 의미하며, 회색 픽셀의 값은 175, 하얀색 픽셀의 값은 255의 값이 됩니다.

이 픽셀들의 값을 이용하여 적분 연산을 실행합니다.


sum


sqsum


tiltedsum


다음과 같은 공식을 사용하여 이미지를 변환합니다.

X, Y의 값은 결과 이미지에서 각 픽셀의 값을 의미합니다.

x, y의 값은 계산 이미지에서 각 픽셀의 값을 의미합니다.


위와 같은 sum의 연산 방법을 사용하여 결과를 확인한다면 다음과 같습니다.


여기서 붉은색 위치의 I3 값의 값은 다음 이미지의 픽셀 합과 같습니다.


연두색 위치의 a1:h2 값의 합과 같습니다. 연산 방법의 공식을 이용하여 결과를 얻어냅니다.

배열의 크기가 1이 더 큰 이유는 공식에서 확인할 수 있듯이 x<X, y<Y에 의하여 배열의 크기가 1이 더 크게됩니다.


Cv.Integral(integral, sum, sqsum, tiltedSum);

Cv.Integral()를 사용하여 적분 이미지를 구합니다.

Cv.Integral(계산 이미지, 적분 이미지, 제곱된 적분 이미지, 45° 기울어진 적분 이미지)를 의미합니다.


CvMat src_mat = new CvMat(integral.Height, integral.Width, MatrixType.F64C1);
CvMat sum_mat = new CvMat(sum.Height, sum.Width, MatrixType.F64C1);

for (int i = 0; i < integral.Width; i++)
{
    for (int j = 0; j < integral.Height; j++)
    {
        src_mat[j, i] = integral[j, i].Val0;
    }
}

for (int i = 0; i < sum.Width; i++)
{
    for (int j = 0; j < sum.Height; j++)
    {
        sum_mat[j, i] = sum[j, i].Val0;
    }
}

Console.WriteLine(src_mat);
Console.WriteLine(sum_mat);

CvMat을 이용하여 적분 이미지에 할당된 값을 확인할 수 있습니다.

이미지를 통하여 결과를 확인은 어렵습니다.

픽셀의 값이 255을 넘어가는 경우, 하얀색 픽셀로 처리하여 육안으로는 구분할 수 없습니다.



출력 결과

image

CvMat(Rows=10, Cols=10)
0	0	0	0	0	175	255	255	255	255	
0	0	0	0	0	175	255	255	255	255	
0	0	0	0	0	175	255	255	255	255	
0	0	0	0	0	175	255	255	255	255	
0	0	0	0	0	175	255	255	255	255	
175	175	175	175	175	175	255	255	255	255	
255	255	255	255	255	255	255	255	255	255	
255	255	255	255	255	255	255	255	255	255	
255	255	255	255	255	255	255	255	255	255	
255	255	255	255	255	255	255	255	255	255	



sum

CvMat(Rows=11, Cols=11)
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	175	430	685	940	1195	
0	0	0	0	0	0	350	860	1370	1880	2390	
0	0	0	0	0	0	525	1290	2055	2820	3585	
0	0	0	0	0	0	700	1720	2740	3760	4780	
0	0	0	0	0	0	875	2150	3425	4700	5975	
0	175	350	525	700	875	1925	3455	4985	6515	8045	
0	430	860	1290	1720	2150	3455	5240	7025	8810	10595	
0	685	1370	2055	2740	3425	4985	7025	9065	11105	13145	
0	940	1880	2820	3760	4700	6515	8810	11105	13400	15695	
0	1195	2390	3585	4780	5975	8045	10595	13145	15695	18245



결과

댓글 남기기