욜로 코드 수정으로 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이라는 프로그램을 이용하였다.
위와 같이 좋은 결과 값을 얻어내는 것이 가능하며, 위의 코드들로 cctv 같은 것을 만들 수 있을 것으로 추정된다.
'인공지능 > 실습' 카테고리의 다른 글
[ubuntu] YOLOV4파일을 tflite형식으로 변환하기(convert YOLOV4 to tflite) (0) | 2020.10.22 |
---|---|
[ubuntu,yolo]이미지 라벨링을 위한 YOLO-mark설치(YOLO-mark installation for image labeling) (0) | 2020.10.22 |
[ubuntu] ubuntu에서 YOLOV4 설치(Install Yolo v4 on Ubuntu) (0) | 2020.10.22 |
yolo - v3 다크넷(darknet) 설치(윈도우 환경) (0) | 2020.09.02 |
yolo v3 특정 class만 detection해서 화면에 출력하기 (0) | 2020.08.31 |