반응형

C#과 OpenCvSharp를 이용한 간단한 이미지 변환 예.

 

폼에 Button과 PictureBox를 적당히 배치한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
using OpenCvSharp;
 
namespace OpenCV
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog dlg = new OpenFileDialog();
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    Mat mat = Cv2.ImRead(dlg.FileName);
 
                    if (pictureBox1.Image != null)
                    {
                        pictureBox1.Image.Dispose();
                    }
 
                    // Canny Edge Detection(컬러 이미지를 그레이 이미지로 변환 후 Canny Edge Detection)
                    //Cv2.CvtColor(mat, mat, ColorConversionCodes.BGR2GRAY);
                    //Cv2.Canny(mat, mat, 50, 100);
 
                    // 이미지 샤프닝(가우시안블러 후 샤프닝)
                    Mat blurred = new Mat();
                    Cv2.GaussianBlur(mat, blurred, new OpenCvSharp.Size(), (double)3);
 
                    float alpha = 2.0f;
                    mat = (1 + alpha) * mat - alpha * blurred;
                    //((1 + alpha) * mat - alpha * blurred).ToMat().CopyTo(mat);
 
                    // PictureBox에 이미지 디스플레이(Mat to Bitmap)
                    System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(mat.ToBytes());
                    pictureBox1.Image = new Bitmap(memoryStream);
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }
    }
}
 

 

이미지 샤프닝 예제를 입력하고 빌드한다.

 

프로그램을 실행하고 이미지를 불러오면 샤프닝 처리가 되어 표시된다.

 

원본 이미지

 

1
2
3
4
5
6
7
// 이미지 샤프닝(가우시안블러 후 샤프닝)
Mat blurred = new Mat();
Cv2.GaussianBlur(mat, blurred, new OpenCvSharp.Size(), (double)3);
 
float alpha = 2.0f;
mat = (1 + alpha) * mat - alpha * blurred;
//((1 + alpha) * mat - alpha * blurred).ToMat().CopyTo(mat);
 

 

이미지 샤프닝 코드 부분을 보면 위와같이 Mat 클래스에 +, -, * 등의 연산을 직접한다. 이 때 Mat 클래스는 효율을 높이기 위해 MatExpr 클래스로 변환 되어 연산이 진행된다.

 

위 예제에서는 별 문제 없지만 Mat 클래스 인스턴스의 레퍼런스(포인터)가 함수의 파라미터로 넘어 오고 그 함수에서 계산해서 다시 리턴하는 등의 작업이 진행될 때는 이렇게 계산 결과를 대입하는 경우 계산된 데이터가 제대로 전달 되지 않는다. C++에서는 같은 방식으로 해도 문제가 없다. 내가 모르는 C#의 특성이 있는거 같다.

 

이럴때는 주석 부분과 같이 MatExpr 클래스로 변환 되는 부분을 괄호로 감싸고 MatExpr.ToMat()로 Mat 클래스로 변환해서 다시 Mat.CopyTo()로 복사한다. 아니면 함수의 파라미터 선언을 (ref Mat mat) 처럼 바꿔서 레퍼런스를 주고 받도록 바꾸면 된다. 아래 링크의 경우 델리게이트 선언도 레퍼런스를 주고 받도록 바꿔야 한다.

2022.01.14 - [C#] - OpenCvSharp Simple Camera Example

 

반응형
Posted by J-sean
: