◎ MQTT 프로토콜이란?

- Message Queue TELEMETRY TRANSPORT

- 모바일, 스마트폰 기기, IoT 장비 등에 널리 사용되고 있음

- Broker Pattern 기반의 경량형 메시징 프로토콜

 

Broker Pattern

- 원격 서비스 호출을 통해 상호작용하는 컴포넌트들을 분리하는 분산 소프트웨어 시스템 구조

- 다양한 MQTT용 브로커들이 이미 개발되어 있으며 아래의 링크를 통해 확인할 수 있음

- MQTT Broker List : https://github.com/mqtt/mqtt.org/wiki/servers

 

◎ MQTT 구조

- Broker : 데이터의 중계

- Publisher : 발행(publish)을 통해 데이터를 Broker로 전달

- Subscriber : 구독(subscribe)을 통해 Broker로 부터 데이터를 수신

<MQTT 구조 - 출처 : https://mqtt.org/>

◎ MQTT의 QoS

- 0단계 : 메시지 한번 전달, 수신과정 체크 없음

- 1단계 : 메시지 한번 이상 전달, 추적 없음, 중복 수신 가능성 있음

- 2단계 : 메시지 한번 전달, 핸드셰이킹 모든 과정 체크

- 단계의 상향에 따른 품질 향상이 있으나 속도의 저하 가능성이 있음

 

◎ MQTT 장점

- 단순하고 가벼운 프로토콜

- 메시지의 특성에 따른 QoS 선택 가능

- TLS/SSL 등의 암호화 지원

- 간편한 1:1, 1:N 통신 구축

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
LPCSTR doubleToLPCSTR(double input)
{
    string tempString = to_string(input);
    LPCSTR lpcString = tempString.c_str();
 
    return lpcString;
}
 
LPCSTR intToLPCSTR(double input)
{
    string tempString = to_string(input);
    LPCSTR lpcString = tempString.c_str();
 
    return lpcString;
}
cs
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
#include <iostream>
#include <fstream>
#include "opencv2/core.hpp"
#include <opencv2/core/utility.hpp>
#include "opencv2/highgui.hpp"
#include "opencv2/cudaoptflow.hpp"
#include "opencv2/cudaarithm.hpp"
#include "opencv2/imgproc.hpp"
 
using namespace std;
using namespace cv;
using namespace cv::cuda;
 
 
int main()
{
    VideoCapture capture("D:/test.mp4");
 
    if (!capture.isOpened())
    {
        printf("AVI file can not open.\n");
        return -1;
    }
 
    // Optical 객체 초기화
    int opticalWindowSize = 15;
    Ptr<cuda::FarnebackOpticalFlow> farn = cuda::FarnebackOpticalFlow::create(50.5false, opticalWindowSize, 105);
 
    // 영상 저장용 Mat
    Mat framePrev;
    Mat frameCurr;
    capture >> framePrev;
    cv::cvtColor(framePrev, framePrev, cv::COLOR_BGR2GRAY);
 
 
 
    while (1)
    {
        capture >> frameCurr;
        if (frameCurr.empty()) //Is video end?
            break;
 
        cv::cvtColor(frameCurr, frameCurr, cv::COLOR_BGR2GRAY);
 
        // GPU Mat 초기화
        GpuMat g_framePrev(framePrev);
        GpuMat g_frameCurr(frameCurr);
 
        // Optical 동작
        GpuMat g_flow(frameCurr.size(), CV_32FC2);
        farn->calc(g_framePrev, g_frameCurr, g_flow);
 
        // 결과 저장
        Mat flowMat;
        g_flow.download(flowMat);
 
        // 결과 그리기
        for (int y = 0; y < frameCurr.rows - 1; y += opticalWindowSize)
        {
            for (int x = 0; x < frameCurr.cols - 1; x += opticalWindowSize)
            {
                // get the flow from y, x position * 10 for better visibility
                const Point2f flowatxy = flowMat.at<Point2f>(y, x) ;
                // draw line at flow direction
                int tempSize = 1;
                line(frameCurr, Point(x, y), Point(cvRound(x + tempSize * flowatxy.x), cvRound(y + tempSize * flowatxy.y)), Scalar(02550), 1);
                // draw initial point
                circle(frameCurr, Point(x, y), 1, Scalar(00255), -1);
            }
        }
 
        cv::imshow("Display window", frameCurr);
        cv::waitKey(1);
 
        // 모든 반복이 끝나고 이전 프레임 업데이트
        framePrev = frameCurr;
    }
 
    return 0;
}
cs
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
#include <iostream>
#include <sstream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
 
using namespace cv;
using namespace std;
 
int main(int argc, char* argv[])
{
    VideoCapture capture(0);
    if (!capture.isOpened()) {
        //error in opening the video input
        cerr << "Unable to open video " << endl;
        return 0;
    }
 
    // Mat things
    Mat frame, prevFrame, optical;
    UMat  flowUmat;
 
    // store init frame
    capture >> prevFrame;
    cvtColor(prevFrame, prevFrame, COLOR_BGR2GRAY);
 
    // optical setting
    int opticalWindowSize = 5;
 
    while (true) {
        capture >> frame;
        if (frame.empty())
            break;
 
        optical = frame;
 
        // calculate optical flow
        cvtColor(optical, optical, COLOR_BGR2GRAY);
        calcOpticalFlowFarneback(prevFrame, optical, flowUmat, 0.41, opticalWindowSize, 281.20);
 
        int j = 0;
        Mat flow;
        flowUmat.copyTo(flow);
        for (int y = 0; y < optical.rows; y += opticalWindowSize)
        {
            for (int x = 0; x < frame.cols; x += opticalWindowSize)
            {
                // get the flow from y, x position * 10 for better visibility
                const Point2f flowatxy = flow.at<Point2f>(y, x);
                // draw line at flow direction
                line(optical, Point(x, y), Point(cvRound(x + flowatxy.x), cvRound(y + flowatxy.y)), Scalar(25500));
                // draw initial point
                circle(optical, Point(x, y), 1, Scalar(000), -1);
            }
        }
 
        //show the current frame and the fg masks
        imshow("Frame", frame);
        imshow("Optical", optical);
 
        prevFrame = frame;
        cvtColor(prevFrame, prevFrame, COLOR_BGR2GRAY);
 
        //get the input from the keyboard
        int keyboard = waitKey(30);
        if (keyboard == 'q' || keyboard == 27)
            break;
 
    }
    return 0;
}
 
cs

Cudacodec에서 사용하는 구조체 중 cuda.lib에 포함된 것들이 링크가 되지않아 에러가 발생

 

링커-입력에 cuda.lib 추가로 해결

 

 

오류 코드 상세 : 

 

심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태
오류 LNK2019 cuCtxPushCurrent_v2 외부 기호(참조 위치: "public: void __cdecl cv::cudacodec::detail::VideoDecoder::create(struct cv::cudacodec::FormatInfo const &)" (?create@VideoDecoder@detail@cudacodec@cv@@QEAAXAEBUFormatInfo@34@@Z) 함수)에서 확인하지 못했습니다. opencv_world D:\trunk_vc14\1.library\Opencv\opencv-4.5.2\mybuild\modules\world\video_decoder.obj 1

 

심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태
오류 LNK2019 cuCtxPopCurrent_v2 외부 기호(참조 위치: "public: void __cdecl cv::cudacodec::detail::VideoDecoder::create(struct cv::cudacodec::FormatInfo const &)" (?create@VideoDecoder@detail@cudacodec@cv@@QEAAXAEBUFormatInfo@34@@Z) 함수)에서 확인하지 못했습니다. opencv_world D:\trunk_vc14\1.library\Opencv\opencv-4.5.2\mybuild\modules\world\video_decoder.obj 1

 

심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태
오류 LNK2019 cuCtxGetCurrent 외부 기호(참조 위치: "public: __cdecl `anonymous namespace'::VideoReaderImpl::VideoReaderImpl(struct cv::Ptr<class cv::cudacodec::detail::VideoSource> const &)" (??0VideoReaderImpl@?A0xe4b1a0fc@@QEAA@AEBU?$Ptr@VVideoSource@detail@cudacodec@cv@@@cv@@@Z) 함수)에서 확인하지 못했습니다. opencv_world D:\trunk_vc14\1.library\Opencv\opencv-4.5.2\mybuild\modules\world\video_reader.obj 1

Opencv Cudacodec과 DNN 모듈을 이용한 비디오 디코딩&객체검출

 

Opencv 4.5.2 + Contirb 모듈

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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include <iostream>
#include <queue>
#include <iterator>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <chrono>
 
#include "opencv2/opencv_modules.hpp"
 
#include <stdio.h>
#include <vector>
#include <numeric>
#include <time.h>
#include <Windows.h>
 
#include "opencv2/core.hpp"
#include "opencv2/cudacodec.hpp"
 
#include <opencv2/dnn.hpp>
#include <opencv2/dnn/all_layers.hpp>
 
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
 
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/cudawarping.hpp>
 
 
using namespace std;
using namespace cv;
 
constexpr float CONFIDENCE_THRESHOLD = 0;
constexpr float NMS_THRESHOLD = 0.4;
constexpr int NUM_CLASSES = 5;
 
 
// colors for bounding boxes
const cv::Scalar colors[] = {
    { 0255255 },
    { 2552550 },
    { 02550 },
    { 25500 }
};
const auto NUM_COLORS = sizeof(colors) / sizeof(colors[0]);
 
 
void gpuVideoThread(int threadNum, int channel4gpu, string videoPath, int bimshow)
{
    if (threadNum < channel4gpu)
    {
        cv::cuda::setDevice(0);
    }
    else if (threadNum < channel4gpu * 2)
    {
        cv::cuda::setDevice(1);
    }
    else if (threadNum < channel4gpu * 3)
    {
        cv::cuda::setDevice(2);
    }
    else if (threadNum < channel4gpu * 4)
    {
        cv::cuda::setDevice(3);
    }
 
    // 비디오 디코더
    cuda::GpuMat gImg;
    cv::Ptr<cv::cudacodec::VideoReader> d_reader = cv::cudacodec::createVideoReader(videoPath);
    
    // Detection용 Mat
    cv::Mat frame, blob;
    std::vector<cv::Mat> detections;
 
 
    // fps 계산용
    int frameCnt = 0;
    int nPrevSec = -1;
 
    SYSTEMTIME stNow;
 
    // Yolo
    auto net = cv::dnn::readNetFromDarknet("D:/test/352.cfg""D:/test/352.weights");
    std::vector<std::string> class_names;
    class_names.push_back("person"); class_names.push_back("car"); class_names.push_back("truck"); class_names.push_back("motoby"); class_names.push_back("bus");
    net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
    net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA_FP16);
    auto output_names = net.getUnconnectedOutLayersNames();
 
    // 루프 시작
    for (;;)
    {
        if (!d_reader->nextFrame(gImg))
            break;
 
        // fps 계산용
        frameCnt++;
 
        // gpu mat 상태로 연산
        int imageSize = 352;
        cv::cuda::cvtColor(gImg, gImg, COLOR_RGBA2RGB);
        cv::cuda::resize(gImg, gImg, Size(imageSize, imageSize));
 
        // 일반 Mat로 변환
        gImg.download(frame);
        
        // YOLO
        cv::dnn::blobFromImage(frame, blob, 1.0/255, cv::Size(imageSize, imageSize), cv::Scalar(), truefalse, CV_32F);
        net.setInput(blob);
        net.forward(detections, output_names);
 
        // 01 ----------------------------------------
        std::vector<int> indices[NUM_CLASSES];
        std::vector<cv::Rect> boxes[NUM_CLASSES];
        std::vector<float> scores[NUM_CLASSES];
 
        for (auto& output : detections)
        {
            const auto num_boxes = output.rows;
            for (int i = 0; i < num_boxes; i++)
            {
                auto x = output.at<float>(i, 0* frame.cols;
                auto y = output.at<float>(i, 1* frame.rows;
                auto width = output.at<float>(i, 2* frame.cols;
                auto height = output.at<float>(i, 3* frame.rows;
                cv::Rect rect(x - width / 2, y - height / 2, width, height);
 
                for (int c = 0; c < NUM_CLASSES; c++)
                {
                    auto confidence = *output.ptr<float>(i, 5 + c);
                    if (confidence >= CONFIDENCE_THRESHOLD)
                    {
                        boxes[c].push_back(rect);
                        scores[c].push_back(confidence);
                    }
                }
            }
        }
 
        for (int c = 0; c < NUM_CLASSES; c++)
            cv::dnn::NMSBoxes(boxes[c], scores[c], 0.0, NMS_THRESHOLD, indices[c]);
 
        for (int c = 0; c < NUM_CLASSES; c++)
        {
            for (size_t i = 0; i < indices[c].size(); ++i)
            {
                const auto color = colors[c % NUM_COLORS];
 
                auto idx = indices[c][i];
                const auto& rect = boxes[c][idx];
                cv::rectangle(frame, cv::Point(rect.x, rect.y), cv::Point(rect.x + rect.width, rect.y + rect.height), color, 3);
 
                std::ostringstream label_ss;
                label_ss << class_names[c] << ": " << std::fixed << std::setprecision(2<< scores[c][idx];
                auto label = label_ss.str();
 
                int baseline;
                auto label_bg_sz = cv::getTextSize(label.c_str(), cv::FONT_HERSHEY_COMPLEX_SMALL, 11&baseline);
                cv::rectangle(frame, cv::Point(rect.x, rect.y - label_bg_sz.height - baseline - 10), cv::Point(rect.x + label_bg_sz.width, rect.y), color, cv::FILLED);
                cv::putText(frame, label.c_str(), cv::Point(rect.x, rect.y - baseline - 5), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(000));
            }
        }
 
        // 이미지 출력
        //resize(frame, frame, Size(160, 160));
        if (bimshow == 1)
        {
            imshow(to_string(threadNum), frame);
        }
 
        // 시간 측정 종료 및 출력
        ::GetLocalTime(&stNow);
        if (stNow.wSecond != nPrevSec)
        {
            nPrevSec = stNow.wSecond;
            cout << frameCnt << " / ";
 
            frameCnt = 0;
        }
        waitKey(1);
        Sleep(30);
    }
}
 
 
int main(int argc, char **argv)
{
    //string videoPath = "rtsp://admin:admin13579@192.168.0.94/profile2/media.smp";
    string videoPath = "D:/test/test.mp4";
 
 
    // 총 쓰레드 수
    int num_threads = 8;
 
    // 그래픽 카드당 처리 채널 수
    int channel4grapich = 8;
 
    int bimshow = 1;
 
    if (argc == 5)
    {
        num_threads = atoi(argv[1]);
        channel4grapich = atoi(argv[2]);
        videoPath = argv[3];
        bimshow = atoi(argv[4]);
    }
 
    // 쓰레드 벡터
    vector<std::thread*> thread_Ptr_vec;
 
 
    // 쓰레드 생성
    for (int i = 0; i < num_threads; i++)
    {
        thread_Ptr_vec.push_back(new std::thread(gpuVideoThread, i, channel4grapich, videoPath, bimshow));
    }
 
    for (int i = 0; i < num_threads; i++)
    {
        thread_Ptr_vec[i]->join();
    }
 
 
    return 0;
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    BROWSEINFO bInfo;
    TCHAR szBuffer[512];                    
 
    ::ZeroMemory(&bInfo, sizeof(BROWSEINFO));
    ::ZeroMemory(szBuffer, 512);
 
    bInfo.hwndOwner = GetSafeHwnd();
    bInfo.lpszTitle = _T("이미지가 들어있는 폴더를 선택하세요.");
    bInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_RETURNONLYFSDIRS;
    LPITEMIDLIST pItemIdList = ::SHBrowseForFolder(&bInfo);
    ::SHGetPathFromIDList(pItemIdList, szBuffer);              
 
    CString str;
    str.Format(_T("%s"), szBuffer);
cs

opencv 3.4.10, dnn 모듈 사용

 

 

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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include <fstream>
#include <sstream>
#include <iostream>
#include <string.h>
 
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
 
using namespace cv;
using namespace dnn;
using namespace std;
 
// Initialize the parameters
float confThreshold = 0.5// Confidence threshold
float maskThreshold = 0.3// Mask threshold
 
vector<string> classes;
vector<Scalar> colors;
 
// Draw the predicted bounding box
void drawBox(Mat& frame, int classId, float conf, Rect box, Mat& objectMask);
 
// Postprocess the neural network's output for each frame
void postprocess(Mat& frame, const vector<Mat>& outs);
 
int main()
{
    // Load names of classes
    string classesFile = "mscoco_labels.names";
    ifstream ifs(classesFile.c_str());
    string line;
    while (getline(ifs, line)) classes.push_back(line);
 
    // Load the colors
    string colorsFile = "colors.txt";
    ifstream colorFptr(colorsFile.c_str());
    while (getline(colorFptr, line)) {
        char* pEnd;
        double r, g, b;
        r = strtod(line.c_str(), &pEnd);
        g = strtod(pEnd, NULL);
        b = strtod(pEnd, NULL);
        Scalar color = Scalar(r, g, b, 255.0);
        colors.push_back(Scalar(r, g, b, 255.0));
    }
 
    // Give the configuration and weight files for the model
    String textGraph = "mask_rcnn_inception_v2_coco_2018_01_28.pbtxt";
    String modelWeights = "frozen_inference_graph.pb";
 
    // Load the network
    Net net = readNetFromTensorflow(modelWeights, textGraph);
    net.setPreferableBackend(DNN_BACKEND_OPENCV);
    net.setPreferableTarget(DNN_TARGET_CPU);
 
    // Open a video file or an image file or a camera stream.
    string str, outputFile;
    VideoCapture cap;
    VideoWriter video;
    Mat frame, blob;
 
    outputFile = "mask_rcnn_out_cpp.avi";
 
    // Open the webcam
    cap.open(0);
 
    // Get the video writer initialized to save the output video
    video.open(outputFile, VideoWriter::fourcc('M''J''P''G'), 28, Size(cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT)));
 
    // Create a window
    static const string kWinName = "Deep learning object detection in OpenCV";
    namedWindow(kWinName, WINDOW_NORMAL);
 
    // Process frames.
    while (waitKey(1< 0)
    {
        // get frame from the video
        cap >> frame;
 
        // Stop the program if reached end of video
        if (frame.empty()) {
            cout << "Done processing !!!" << endl;
            cout << "Output file is stored as " << outputFile << endl;
            waitKey(3000);
            break;
        }
        // Create a 4D blob from a frame.
        blobFromImage(frame, blob, 1.0, Size(frame.cols, frame.rows), Scalar(), truefalse);
        //blobFromImage(frame, blob);
 
        //Sets the input to the network
        net.setInput(blob);
 
        // Runs the forward pass to get output from the output layers
        std::vector<String> outNames(2);
        outNames[0= "detection_out_final";
        outNames[1= "detection_masks";
        vector<Mat> outs;
        net.forward(outs, outNames);
 
        // Extract the bounding box and mask for each of the detected objects
        postprocess(frame, outs);
 
        // Put efficiency information. The function getPerfProfile returns the overall time for inference(t) and the timings for each of the layers(in layersTimes)
        vector<double> layersTimes;
        double freq = getTickFrequency() / 1000;
        double t = net.getPerfProfile(layersTimes) / freq;
        string label = format("Mask-RCNN on 2.5 GHz Intel Core i7 CPU, Inference time for a frame : %0.0f ms", t);
        putText(frame, label, Point(015), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(000));
 
        // Write the frame with the detection boxes
        Mat detectedFrame;
        frame.convertTo(detectedFrame, CV_8U);
        video.write(detectedFrame);
 
        imshow(kWinName, frame);
 
    }
 
    cap.release();
    video.release();
 
    return 0;
}
 
// For each frame, extract the bounding box and mask for each detected object
void postprocess(Mat& frame, const vector<Mat>& outs)
{
    Mat outDetections = outs[0];
    Mat outMasks = outs[1];
 
    // Output size of masks is NxCxHxW where
    // N - number of detected boxes
    // C - number of classes (excluding background)
    // HxW - segmentation shape
    const int numDetections = outDetections.size[2];
    const int numClasses = outMasks.size[1];
 
    outDetections = outDetections.reshape(1, outDetections.total() / 7);
    for (int i = 0; i < numDetections; ++i)
    {
        float score = outDetections.at<float>(i, 2);
        if (score > confThreshold)
        {
            // Extract the bounding box
            int classId = static_cast<int>(outDetections.at<float>(i, 1));
            int left = static_cast<int>(frame.cols * outDetections.at<float>(i, 3));
            int top = static_cast<int>(frame.rows * outDetections.at<float>(i, 4));
            int right = static_cast<int>(frame.cols * outDetections.at<float>(i, 5));
            int bottom = static_cast<int>(frame.rows * outDetections.at<float>(i, 6));
 
            left = max(0, min(left, frame.cols - 1));
            top = max(0, min(top, frame.rows - 1));
            right = max(0, min(right, frame.cols - 1));
            bottom = max(0, min(bottom, frame.rows - 1));
            Rect box = Rect(left, top, right - left + 1, bottom - top + 1);
 
            // Extract the mask for the object
            Mat objectMask(outMasks.size[2], outMasks.size[3], CV_32F, outMasks.ptr<float>(i, classId));
 
            // Draw bounding box, colorize and show the mask on the image
            drawBox(frame, classId, score, box, objectMask);
 
        }
    }
}
 
// Draw the predicted bounding box, colorize and show the mask on the image
void drawBox(Mat& frame, int classId, float conf, Rect box, Mat& objectMask)
{
    //Draw a rectangle displaying the bounding box
    rectangle(frame, Point(box.x, box.y), Point(box.x + box.width, box.y + box.height), Scalar(25517850), 3);
 
    //Get the label for the class name and its confidence
    string label = format("%.2f", conf);
    if (!classes.empty())
    {
        CV_Assert(classId < (int)classes.size());
        label = classes[classId] + ":" + label;
    }
 
    //Display the label at the top of the bounding box
    int baseLine;
    Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.51&baseLine);
    box.y = max(box.y, labelSize.height);
    rectangle(frame, Point(box.x, box.y - round(1.5*labelSize.height)), Point(box.x + round(1.5*labelSize.width), box.y + baseLine), Scalar(255255255), FILLED);
    putText(frame, label, Point(box.x, box.y), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(000), 1);
 
    Scalar color = colors[classId%colors.size()];
 
    // Resize the mask, threshold, color and apply it on the image
    resize(objectMask, objectMask, Size(box.width, box.height));
    Mat mask = (objectMask > maskThreshold);
    Mat coloredRoi = (0.3 * color + 0.7 * frame(box));
    coloredRoi.convertTo(coloredRoi, CV_8UC3);
 
    // Draw the contours on the image
    vector<Mat> contours;
    Mat hierarchy;
    mask.convertTo(mask, CV_8U);
    findContours(mask, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
    drawContours(coloredRoi, contours, -1, color, 5, LINE_8, hierarchy, 100);
    coloredRoi.copyTo(frame(box), mask);
 
}
cs
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
#include <iostream>
 
#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
 
using namespace cv;
using namespace std;
 
int main() 
{
    // init mat
    Mat img, grayImg;
 
    // load image
    img        = imread("이미지 파일 경로", cv::IMREAD_COLOR);
    grayImg = imread("이미지 파일 경로", cv::IMREAD_GRAYSCALE);
 
    // check image
    if (img.empty() || grayImg.empty())
    {
        cout <<"image loading fail" << std::endl;
        return -1;
    }
 
    // show image
    imshow("ori image", img);
    imshow("gray image", grayImg);
 
    // wait
    waitKey(0);
 
    return 0;
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string>
 
using namespace std;
 
int main()
{
    char before[100= {"Char to String"};
    string after(char);
 
    cout << after << endl;
 
    return 0;
}
cs