C# OpenCV 강좌 : 제 55강 - 적분
적분(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
은 제곱된 적분 이미지
를 의미합니다.
tiltedsum
은 45° 기울어진 적분 이미지
를 의미합니다.
위와 같은 이미지를 입력한다면, 각 픽셀들의 값은 다음과 같습니다.
검은색 픽셀
의 값은 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
결과
공유하기


댓글 남기기