OpenCvSharp for Network

OpenCV 2021. 12. 28. 22:45 |
반응형

C#에서 OpenCV Mat 데이터를 네트워크로 송수신 할 수 있도록 준비하는 과정을 시뮬레이션 해 보자.

아래 링크의 글에서 비트맵이 아닌 OpenCV Mat 데이터 송수신 과정이라 보면 된다.

2021.12.25 - [C#] - C# TCP/IP Image transfer - 이미지(파일) 전송 3

 

폼에 PictureBox, Button을 적당히 배치한다.

 

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
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;
using System.IO;
 
namespace OpenCV
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            // 클라이언트 시뮬레이션
            // OpenCV Matrix를 생성하고 바이트 배열로 변환한다.
            Mat clientImage = new Mat("Barbara.jpg");
            byte[] data = clientImage.ToBytes(".jpg"); // ".jpg", ".png", ".bmp"
            //MemoryStream clientMemoryStream = clientImage.ToMemoryStream();
            //byte[] data = clientMemoryStream.ToArray();
 
            // 네트워크 시뮬레이션
            // ...
            // 클라이언트에서 OpenCV Matrix 바이트 배열(data)을 서버로 전송
 
            // 서버 시뮬레이션
            // 클라이언트에서 받은 바이트 배열(data)을 메모리 스트림으로
            // 변환 후 다시 비트맵으로 변환한다.
            MemoryStream serverMemoryStream = new MemoryStream(data);
            Bitmap bitmap = new Bitmap(serverMemoryStream);
            //Mat serverImage = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);
            //Cv2.ImShow("Server Image", serverImage);
            pictureBox1.Image = bitmap;
        }
    }
}
 

 

클라이언트에서 Mat.ToBytes()가 핵심이다. (메모리 스트림으로 변환할 필요가 없다)

소스를 입력하고 빌드한다.

 

실행하면 버튼만 나타난다.

 

버튼을 클릭하면 이미지가 표시된다.

 

반응형
Posted by J-sean
:

OpenCV with C#

OpenCV 2021. 11. 20. 10:22 |
반응형

C#으로 OpenCV를 사용해 보자.

 

새로운 프로젝트를 만든다.

 

C# - Windows - Desktop - Windows Forms App (.NET Framework)

 

적당한 이름과 위치를 지정한다.

 

Tools - Nuget Package Manager - Manage Nuget Packages for Solution...

 

 

Browse - OpenCV를 검색하고 OpenCvSharp4.Windows by shimat 선택, 오른쪽 창에서 현재 프로젝트(OpenCV)를 선택하고 Install을 클릭한다.

 

OK를 클릭한다.

 

설치가 완료되면 폼에 Button과 Picture Box를 하나씩 배치한다.

 

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
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();
                    }
 
                    // Mat to Bitmap 1
                    //Bitmap bitmap = new Bitmap(mat.ToMemoryStream());
                    //pictureBox1.Image = bitmap;
 
                    // Mat to Bitmap 2
                    //Bitmap bitmap = (Bitmap)Image.FromStream(mat.ToMemoryStream());
                    //pictureBox1.Image = bitmap;
 
                    // Mat to Bitmap 3
                    System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(mat.ToBytes());
                    pictureBox1.Image = new Bitmap(memoryStream);
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }
    }
}
 

 

OpenCvSharp를 using 선언하고 버튼 클릭 이벤트 핸들러를 작성한다.

 

 

실행하고 버튼을 클릭해 적당한 그래픽 파일을 선택한다.

 

반응형
Posted by J-sean
:
반응형

Linux가 아닌 Windows에서는 Microsoft Visual C++을 사용하는 경우가 많다. 아래 링크와 같이 Qt를 설치한다.

2021.09.25 - [C, C++] - Qt6 설치 및 간단한 사용법

 

Qt Widgets Application 프로젝트를 생성하고 프로젝트명.pro 파일을 확인한다.

 

프로젝트명.pro 파일을 위와 같이 수정한다. (opencv는 C:\opencv에 설치되어 있다)

CONFIG(debug, debug|release) {
    LIBS += -lopencv_world453d
}

CONFIG(release, debug|release) {
    LIBS += -lopencv_world453
}

opencv_world453은 C:\opencv\build\x64\vc15\bin 폴더의 opencv_worldXXX.dll, opencv_worldXXXd.dll 파일을 참고해 작성한다.

 

Projects - Build & Run - Run - Environment - Path 에 C:\opencv\build\x64\vc15\bin을 추가한다.

 

UI Design에서 Pushbutton을 하나 추가하고 우클릭 - Go to slot...을 클릭한다.

 

 

clicked()를 선택한다.

 

on_pushButton_clicked()를 위와 같이 수정한다. (상단에 opencv.hpp가 include 되어있다)

 

프로젝트를 빌드하고 XXX-Debug 폴더에 사진 파일을 복사한다.

 

실행하면 위와 같은 위도우가 나타난다. PushButton을 클릭하자.

 

 

Barbara palvin 사진이 출력된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 OpenCV 이미지(cv::Mat)를 Qt로(QImage::QImage) 디스플레이 해 보자.

(cv::Mat ↔  QImage::QImage)

 

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <opencv2/opencv.hpp>
 
class Picture : public QWidget
{
public:
    Picture(QWidget* parent = 0);
    ~Picture();
 
protected:
    void paintEvent(QPaintEvent* event);
    // This event handler can be reimplemented in a subclass to receive paint events passed in event.
    void drawPicture(QPainter* qp);
    QImage Mat2QImage(cv::Mat const& src);
    cv::Mat QImage2Mat(QImage const& src);
 
private:
    int height;
    int width;
    QImage qtImage;
    cv::Mat cvImage;
};
 
Picture::Picture(QWidget* parent) : QWidget(parent)
{
    //image.load("Barbara Palvin.png");
    //cvimage = QImage2Mat(image);
 
    //Read images from OpenCV. Not from Qt.
    cvImage = cv::imread("Barbara Palvin.png", cv::IMREAD_COLOR);
    if (cvImage.empty())
    {
        std::cerr << "Image load failed." << std::endl;
 
        exit(EXIT_FAILURE);
    }
 
    cv::Mat tempCvImage;
    cv::cvtColor(cvImage, tempCvImage, cv::COLOR_RGB2GRAY);
 
    qtImage = Mat2QImage(tempCvImage);
    tempCvImage = QImage2Mat(qtImage);
 
    cv::resize(tempCvImage, tempCvImage, cv::Size(), 1.51.5);
    cv::imshow("OpenCV", tempCvImage);
 
    height = qtImage.height();
    width = qtImage.width();
 
    this->resize(width, height);
}
 
Picture::~Picture()
{
 
}
 
void Picture::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e);
    // Q_UNUSED( name)
    // Indicates to the compiler that the parameter with the specified name is not used in the body
    // of a function. This can be used to suppress compiler warnings while allowing functions to be
    // defined with meaningful parameter names in their signatures.
 
    QPainter qp(this);
    drawPicture(&qp);
}
 
void Picture::drawPicture(QPainter* qp)
{
    qp->drawImage(00, qtImage);
}
 
QImage Picture::Mat2QImage(cv::Mat const& src)
{
    cv::Mat temp;
    cv::cvtColor(src, temp, cv::COLOR_BGR2RGB);
    QImage dest((const uchar*)temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
    dest.bits();
    // Enforce deep copy
    // See documentation of QImage::QImage (const uchar * data, int width, int height, Format format)
 
    return dest;
}
 
cv::Mat Picture::QImage2Mat(QImage const& src)
{
    cv::Mat temp(src.height(), src.width(), CV_8UC3, (uchar*)src.bits(), src.bytesPerLine());
    cv::Mat result; // Deep copy
    cv::cvtColor(temp, result, cv::COLOR_BGR2RGB);
 
    return result;
}
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    Picture window;
    window.setWindowTitle("Qt");
    //window.resize(width, height);
 
    window.show();
 
    return app.exec();
}
 
 

 

소스를 입력한다. (qtcv.cpp)

 

컴파일(빌드)하고 실행하면 cv::imshow(), QPainter::drawImage() 모두 잘 표시된다. (OpenCV는 50% 확대)

 

반응형
Posted by J-sean
:
반응형

최신 버전의 OpenCV를 리눅스나 라즈베리 파이에 설치하기 위해서는 길고 지루한 과정을 거쳐야 한다. 꼭 최신 버전의 OpenCV가 필요한게 아니라면 간단하게 설치하고 사용해 보자.

 

libopencv-dev를 설치한다.

 

3.2.0 버전의 OpenCV가 설치 되었다.

 

텍스트 편집기에서 간단한 소스를 입력하고 저장한다.

 

컴파일 한다. pkg-config 명령어를 감싸고 있는 ` 기호는 Tab 키 위에 있는 backtick이다.

 

 

컴파일된 파일을 실행하면 라즈베리 파이에 연결된 카메라가 작동되고 sample.jpg가 생성된다.

 

sample.jpg

 

라즈베리 파이가 아닌 PC(우분투)에서 위 내용을 진행하면 opencv2/opencv.hpp가 없다는 에러가 발생하게 된다.

 

설치한 libopencv-dev의 버전이 다르기 때문인데 PC(우분투)에서는 라즈베리 파이보다 높은 버전의(4.2.0) opencv가 설치된다.

 

 

pkg-config --list-all 명령으로 확인된 opencv4 옵션을 사용해 컴파일 한다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에 OpenCV-Python을 설치하자.


opencv-python을 설치하면 numpy도 함께 설치된다.


간단한 opencv 예제를 입력하고 파이썬 파일로 저장한다.


예제를 실행하면 이미지가 출력된다.


GUI가 없는 리눅스 서버에서는 실행되지 않는다. 이미지를 디스플레이 하는 코드가 포함되었기 때문인데 이미지 읽기, 저장, 연산등의 작업만 하는 프로그램은 문제 없이 실행된다.


반응형
Posted by J-sean
:
반응형

It describes how to detect faces with Haar-cascade classifier.

OpenCV에서 Haar-cascade classifier를 이용한 얼굴 검출.


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
#include <opencv2/opencv.hpp>
 
using namespace std;
using namespace cv;
 
int main()
{
    Mat src = imread("girl.jpg");
 
    if (src.empty()) {
        cerr << "Image load failed." << endl;
 
        return -1;
    }
 
    CascadeClassifier classifier("haarcascade_frontalface_default.xml");
    // Cascade classifier class for object detection.
 
    if (classifier.empty()) {
        cerr << "Classifier load failed." << endl;
 
        return -1;
    }
 
    vector<Rect> faces;
    classifier.detectMultiScale(src, faces);
    // Detects objects of different sizes in the input image.
    // The detected objects are returned as a list of rectangles.
 
    for (Rect rect : faces) {
        rectangle(src, rect, Scalar(00255), 2);
    }
 
    imshow("Face Detection", src);
 
    waitKey(0);
 
    return 0;
}



Run the program and see the result.


Detected two babies' faces.


It couldn't detect a face with shades and detected some wrong objects.


반응형
Posted by J-sean
:
반응형

It shows how to detect and decode a QR Code.

OpenCV에서 QR코드를 감지하고 내용을 확인할 수 있다.


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
60
61
#include <Windows.h>
#include <opencv2/opencv.hpp>
 
using namespace std;
using namespace cv;
 
int main()
{
    VideoCapture cap(0);
 
    if (!cap.isOpened()) {
        cerr << "Camera open failed." << endl;
 
        return -1;
    }
 
    QRCodeDetector detector;
 
    Mat frame;
    vector<Point> points;
    String msg;
 
    while (true) {
        cap >> frame;
 
        if (frame.empty()) {
            cerr << "Empty frame." << endl;
 
            break;
        }
 
        msg = detector.detectAndDecode(frame, points); // Both detects and decodes QR code.
 
        if (!msg.empty()) {
            polylines(frame, points, true, Scalar(00255), 2);
            putText(frame, msg, Point(1030), FONT_HERSHEY_PLAIN, 2, Scalar(00255), 2);
 
            if (msg.substr(04== "http") {
                imshow("QR Code", frame);
 
                if (MessageBox(NULL, (msg + " is a website address.\nDo you want to visit?").c_str(), "QR Code", MB_YESNO) == IDYES) {
                    ShellExecute(NULL"open", msg.c_str(), NULLNULL, SW_SHOW);
                    // Performs an operation on a specified file.
                }
                else {
                    continue;
                }
            }
        }
        else {
            putText(frame, "No QR code detected", Point(1030), FONT_HERSHEY_PLAIN, 2, Scalar(00255), 2);
        }
 
        imshow("QR Code", frame);
 
        if (waitKey(10== 27)
            break;
    }
 
    return 0;
}



Run the program. It says 'No QR code detected' at first.


QR code with a message.


QR code with a website address.


If the first 4 letters of the message are 'http', it opens the website with the default web browser.



반응형
Posted by J-sean
: