728x90

욜로 코드 수정으로 coco 데이터를 이용하여 특정 class만 웹캠 화면에 표기하도록 하였다.

twobeach.tistory.com/6<-특정 class만 표기하는 것

 

그것을 응용해서 욜로v3에서 사람이 감지되면 정보를 라즈베리파이로 소켓통신을 통해 정보를 넘기도록 하자

 

먼저 소켓통신 코드를 작성하여 서버와 클라이언트를 만들어준다.

(소켓통신을 할 때 스레드를 이용하여 나중에 여러 장비로 응용 프로젝트를 해보고 싶어서 스레드를 이용하였습니다.)

 

server.py 

import socket
import threading

 

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('',12345))
server_socket.listen(0)
client_socket, addr = server_socket.accept()

 

def recv_data():

    while True:

        data = client_socket.recv(65535)

        print("receive data : %s" % data.decode('utf-8'))

    client_socket.close()

    

def send_data():

    while True:

        data = input("input data : ")

        client_socket.send(data.encode('utf-8'))

    client_socket.close()

    

    

recv_thread = threading.Thread(target=recv_data)

recv_thread.start()

send_thread = threading.Thread(target=send_data)

send_thread.start()

 

while True:

    pass

client.py

import socket
import threading
import time

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.connect(('192.168.0.95', 12345))


def send_data():

    while True:
        f = open('C:/detectper.txt', 'r')
        line = f.readline()
        if not line:
            sock.send('no_detect!'.encode())
            time.sleep(1)
        else:
            sock.send('person_detect!'.encode())
            time.sleep(1)


    f.close()
    sock.close()


send_thread = threading.Thread(target=send_data())
send_thread.start()

 

 

서버의 경우 스레드를 이용하여 나중에 안드로이드나 다른 장비를 소켓통신이 가능하도록 하였다.

클라이언트의 경우는 해당 detectper.txt가 아무것도 없는 빈 파일일 경우 no_detect!를 보내게 해놨고, 밑에서 설명 하겠지만 yolo의 코드로 사람이 감지되면 1이라는 숫자를 넣어 txt파일을 저장하게 해놨다. 고로 사람이 감지 되었을 때 person_detect! 라는 문구를 라즈베리파이로 보내게 된다.

 

draw_detections_cv_v3

extern "C" void draw_detections_cv_v3(mat_cv* mat, detection *dets, int num, float thresh, char **names, image **alphabet, int classes, int ext_output)
{
    
    try {
        cv::Mat *show_img = (cv::Mat*)mat;
        int i, j;
        if (!show_img) return;
        static int frame_id = 0;
        frame_id++;
        FILE* dp_fp = fopen("C:\\detectper.txt", "wt");

        for (i = 0; i < num; ++i) {
            char labelstr[4096] = { 0 };
            int class_id = -1;
            for (j = 0; j < classes; ++j) {
                int show = strncmp(names[j], "dont_show", 9);
                if (dets[i].prob[j] > thresh && show) {
                    if (class_id < 0) {
                        strcat(labelstr, names[j]);
                        class_id = j;
                        char buff[20];
                        if (dets[i].track_id) {
                            sprintf(buff, " (id: %d)", dets[i].track_id);
                            strcat(labelstr, buff);
                        }
                        sprintf(buff, " (%2.0f%%)", dets[i].prob[j] * 100);
                        strcat(labelstr, buff);
                        printf("%s: %.0f%% ", names[j], dets[i].prob[j] * 100);
                        if (dets[i].track_id) printf("(track = %d, sim = %f) ", dets[i].track_id, dets[i].sim);
                    }
                    else {
                        strcat(labelstr, ", ");
                        strcat(labelstr, names[j]);
                        printf(", %s: %.0f%% ", names[j], dets[i].prob[j] * 100);
                    }
                   

                    fclose(dp_fp);
                    
                    if (strcmp(names[class_id], "person") == 0)
                    {


                        FILE* dp_fp = fopen("C:\\detectper.txt", "wt");
                        fputs("1", dp_fp);
                        fclose(dp_fp);
                    }
                }
            }
            
             if (class_id >= 0) {
                int width = std::max(1.0f, show_img->rows * .002f);
                if (strcmp(names[class_id], "person") != 0)
                    continue;
                    
                    int offset = class_id * 123457 % classes;
                float red = get_color(2, offset, classes);
                float green = get_color(1, offset, classes);
                float blue = get_color(0, offset, classes);
                float rgb[3];

                //width = prob*20+2;

                rgb[0] = red;
                rgb[1] = green;
                rgb[2] = blue;
                box b = dets[i].bbox;
                if (std::isnan(b.w) || std::isinf(b.w)) b.w = 0.5;
                if (std::isnan(b.h) || std::isinf(b.h)) b.h = 0.5;
                if (std::isnan(b.x) || std::isinf(b.x)) b.x = 0.5;
                if (std::isnan(b.y) || std::isinf(b.y)) b.y = 0.5;
                b.w = (b.w < 1) ? b.w : 1;
                b.h = (b.h < 1) ? b.h : 1;
                b.x = (b.x < 1) ? b.x : 1;
                b.y = (b.y < 1) ? b.y : 1;
                //printf("%f %f %f %f\n", b.x, b.y, b.w, b.h);

                int left = (b.x - b.w / 2.)*show_img->cols;
                int right = (b.x + b.w / 2.)*show_img->cols;
                int top = (b.y - b.h / 2.)*show_img->rows;
                int bot = (b.y + b.h / 2.)*show_img->rows;

                if (left < 0) left = 0;
                if (right > show_img->cols - 1) right = show_img->cols - 1;
                if (top < 0) top = 0;
                if (bot > show_img->rows - 1) bot = show_img->rows - 1;

                //int b_x_center = (left + right) / 2;
                //int b_y_center = (top + bot) / 2;
                //int b_width = right - left;
                //int b_height = bot - top;
                //sprintf(labelstr, "%d x %d - w: %d, h: %d", b_x_center, b_y_center, b_width, b_height);

                float const font_size = show_img->rows / 1000.F;
                cv::Size const text_size = cv::getTextSize(labelstr, cv::FONT_HERSHEY_COMPLEX_SMALL, font_size, 1, 0);
                cv::Point pt1, pt2, pt_text, pt_text_bg1, pt_text_bg2;
                pt1.x = left;
                pt1.y = top;
                pt2.x = right;
                pt2.y = bot;
                pt_text.x = left;
                pt_text.y = top - 4;// 12;
                pt_text_bg1.x = left;
                pt_text_bg1.y = top - (3 + 18 * font_size);
                pt_text_bg2.x = right;
                if ((right - left) < text_size.width) pt_text_bg2.x = left + text_size.width;
                pt_text_bg2.y = top;
                cv::Scalar color;
                color.val[0] = red * 256;
                color.val[1] = green * 256;
                color.val[2] = blue * 256;

                // you should create directory: result_img
                //static int copied_frame_id = -1;
                //static IplImage* copy_img = NULL;
                //if (copied_frame_id != frame_id) {
                //    copied_frame_id = frame_id;
                //    if(copy_img == NULL) copy_img = cvCreateImage(cvSize(show_img->width, show_img->height), show_img->depth, show_img->nChannels);
                //    cvCopy(show_img, copy_img, 0);
                //}
                //static int img_id = 0;
                //img_id++;
                //char image_name[1024];
                //sprintf(image_name, "result_img/img_%d_%d_%d_%s.jpg", frame_id, img_id, class_id, names[class_id]);
                //CvRect rect = cvRect(pt1.x, pt1.y, pt2.x - pt1.x, pt2.y - pt1.y);
                //cvSetImageROI(copy_img, rect);
                //cvSaveImage(image_name, copy_img, 0);
                //cvResetImageROI(copy_img);

                cv::rectangle(*show_img, pt1, pt2, color, width, 8, 0);
                if (ext_output)
                    printf("\t(left_x: %4.0f   top_y: %4.0f   width: %4.0f   height: %4.0f)\n",
                    (float)left, (float)top, b.w*show_img->cols, b.h*show_img->rows);
                else
                    printf("\n");

                cv::rectangle(*show_img, pt_text_bg1, pt_text_bg2, color, width, 8, 0);
                cv::rectangle(*show_img, pt_text_bg1, pt_text_bg2, color, CV_FILLED, 8, 0);    // filled
                cv::Scalar black_color = CV_RGB(0, 0, 0);
                cv::putText(*show_img, labelstr, pt_text, cv::FONT_HERSHEY_COMPLEX_SMALL, font_size, black_color, 2 * font_size, CV_AA);
                // cv::FONT_HERSHEY_COMPLEX_SMALL, cv::FONT_HERSHEY_SIMPLEX
            }
        }
        if (ext_output) {
            fflush(stdout);
        }
    }
    catch (...) {
        cerr << "OpenCV exception: draw_detections_cv_v3() \n";
    }
}

해당 조건에 맞게 사람이 없으면 빈 txt파일이 생성되게하고 사람이 감지되면 1이 들어간 txt파일을 생성하게 하였다.

이 모든 조건은 웹캠에서 실시간 화면이 나왔을 때도 실시간 적용이 가능하다.

 

windows 환경에서 python 코드 실행은 pycharm이라는 프로그램을 이용하였다.

 

욜로에서 사람 화면 잡을 때
욜로에서 사람을 detect 시작할 때 라즈베리 터미널창

 

욜로에서 사람을 detect 하지 못할 때 라즈베리 터미널창

위와 같이 좋은 결과 값을 얻어내는 것이 가능하며, 위의 코드들로 cctv 같은 것을 만들 수 있을 것으로 추정된다.

728x90

+ Recent posts