darknetからの物体検出情報をsocket通信で取得する方法のメモ
Jetson nanoでのカメラ追尾とダブリますが、ソースがうまく貼れそうなので、アップしてみます。
あくまで、素人なので間違えている可能性があります。
1. image_opencv.cppの修正
(1) 80行目当たりに/* added source by sakachan */から/**************************/までを追加しました。
#ifndef CV_AA
#define CV_AA cv::LINE_AA
#endif
/* added source by sakachan */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#define SERVER_PATH "/var/tmp/tpf_unix_sock.server"
#define SERVER_PATH "/tmp/foo.sock"
/**************************/
extern "C" {
//struct mat_cv : cv::Mat { };
(2) 820行当たりのdraw_detections_cv_v3関数を以下のように修正
socket通信のclientとして、物体検出情報を出力(フレームの区切りとして、SとEの文字を出力)します。
// ====================================================================
// Draw Detection
// ====================================================================
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;
/*********** added by sakachan ***********/
int err;
int client_socket, rc;
struct sockaddr_un remote;
char start[] = "S\n";
char end[] = "E\n";
char my_buff[256];
char my_str[256];
if (ext_output) {
memset(&remote, 0, sizeof(struct sockaddr_un));
/****************************************/
/* Create a UNIX domain datagram socket */
/****************************************/
client_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
if (client_socket == -1) {
err = errno;
printf("SOCKET ERROR create = %d : %s", err, strerror(err));
// exit(1);
}
/***************************************/
/* Set up the UNIX sockaddr structure */
/* by using AF_UNIX for the family and */
/* giving it a filepath to send to. */
/***************************************/
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SERVER_PATH);
rc = sendto(client_socket, start, strlen(start), 0, (struct sockaddr *) &remote,
sizeof(remote)); // send "S"
if (rc == -1) {
err = errno;
printf("SENDTO ERROR start = %d : %s", err, strerror(err));
close(client_socket);
// exit(1);
}
sprintf(my_buff, "num:%d\n", num);
rc = sendto(client_socket, my_buff, strlen(my_buff), 0, (struct sockaddr *) &remote,
sizeof(remote)); // send "num:x"
if (rc == -1) {
err = errno;
printf("SENDTO ERROR num = %d : %s", err, strerror(err));
close(client_socket);
// exit(1);
}
}
/***************************************/
if (!show_img) return;
static int frame_id = 0;
frame_id++;
for (i = 0; i < num; ++i) {
/*********** added by sakachan ***********/
char out_buff[4096] = { 0 };
/***************************************/
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);
/*********** added by sakachan ***********/
sprintf(my_str,"%s: %.0f%%", names[j], dets[i].prob[j] * 100);
strcat(out_buff, my_str);
/***************************************/
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);
/*********** added by sakachan ***********/
sprintf(my_str,",%s: %.0f%%", names[j], dets[i].prob[j] * 100);
strcat(out_buff, my_str);
/****************************/
}
}
}
if (class_id >= 0) {
int width = std::max(1.0f, show_img->rows * .002f);
//if(0){
//width = pow(prob, 1./2.)*10+1;
//alphabet = 0;
//}
//printf("%d %s: %.0f%%\n", i, names[class_id], prob*100);
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; /* uncomment by sakachan */
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);
// sprintf(labelstr, "x:%d y:%d w:%d h:%d", b_x_center, b_y_center, b_width, b_height); // modified by sakachan
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);
/****** added by sakachan ******/
sprintf(my_buff, ",c_x: %4.0f,c_y: %4.0f,w: %4.0f,h: %4.0f\n",
(float)b_x_center, (float)b_y_center, (float)b_width, (float)b_height);
strcat(out_buff, my_buff);
rc = sendto(client_socket, out_buff, strlen(out_buff), 0, (struct sockaddr *) &remote, sizeof(remote));
if (rc == -1) {
err = errno;
printf("SENDTO ERROR out = %d : %s", err, strerror(err));
// close(client_socket);
// exit(1);
}
} 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) {
/*****************************/
/* Close the socket and exit */
/*****************************/
rc = sendto(client_socket, end, strlen(end), 0, (struct sockaddr *) &remote,
sizeof(remote)); // send "E"
if (rc == -1) {
err = errno;
printf("SENDTO ERROR end = %d : %s", err, strerror(err));
// close(client_socket);
// exit(1);
}
rc = close(client_socket);
/*****************************/
fflush(stdout);
}
}
catch (...) {
cerr << "OpenCV exception: draw_detections_cv_v3() \n";
}
}
// ----------------------------------------
2. socket通信のサーバ側のプログラム(C#)
単純にdarknetからのsocket通信を受信するだけです。
あとは、受信したメッセージを加工して、利用することになります。
Server.cs
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Text;
using System.Collections.Generic;
using System.Net;
class Program
{
private static void Main(string[] args)
{
var unixSocket = "/tmp/foo.sock";
// delete file if it exists
if (System.IO.File.Exists(unixSocket))
System.IO.File.Delete(unixSocket);
// 接続ソケットの準備
Socket s = new Socket(AddressFamily.Unix, SocketType.Dgram, ProtocolType.Unspecified);
var unixEp = new UnixDomainSocketEndPoint(unixSocket);
System.IO.File.Delete(unixSocket);
s.Bind(unixEp);
Console.WriteLine("Server started waiting for client to connect...");
string message = "";
byte[] buffer = new byte[1024];
while (true)
{
int numberOfBytesReceived = s.Receive(buffer, 0, buffer.Length, SocketFlags.None);
if (numberOfBytesReceived <= 0)
{
break;
}
Console.WriteLine(numberOfBytesReceived);
message = System.Text.Encoding.UTF8.GetString(buffer, 0, numberOfBytesReceived);
Console.WriteLine(message);
}
s.Close();
}
}
Jetson nanoでのカメラ追尾とダブリますが、ソースがうまく貼れそうなので、アップしてみます。
あくまで、素人なので間違えている可能性があります。
1. image_opencv.cppの修正
(1) 80行目当たりに/* added source by sakachan */から/**************************/までを追加しました。
#ifndef CV_AA
#define CV_AA cv::LINE_AA
#endif
/* added source by sakachan */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#define SERVER_PATH "/var/tmp/tpf_unix_sock.server"
#define SERVER_PATH "/tmp/foo.sock"
/**************************/
extern "C" {
//struct mat_cv : cv::Mat { };
(2) 820行当たりのdraw_detections_cv_v3関数を以下のように修正
socket通信のclientとして、物体検出情報を出力(フレームの区切りとして、SとEの文字を出力)します。
// ====================================================================
// Draw Detection
// ====================================================================
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;
/*********** added by sakachan ***********/
int err;
int client_socket, rc;
struct sockaddr_un remote;
char start[] = "S\n";
char end[] = "E\n";
char my_buff[256];
char my_str[256];
if (ext_output) {
memset(&remote, 0, sizeof(struct sockaddr_un));
/****************************************/
/* Create a UNIX domain datagram socket */
/****************************************/
client_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
if (client_socket == -1) {
err = errno;
printf("SOCKET ERROR create = %d : %s", err, strerror(err));
// exit(1);
}
/***************************************/
/* Set up the UNIX sockaddr structure */
/* by using AF_UNIX for the family and */
/* giving it a filepath to send to. */
/***************************************/
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SERVER_PATH);
rc = sendto(client_socket, start, strlen(start), 0, (struct sockaddr *) &remote,
sizeof(remote)); // send "S"
if (rc == -1) {
err = errno;
printf("SENDTO ERROR start = %d : %s", err, strerror(err));
close(client_socket);
// exit(1);
}
sprintf(my_buff, "num:%d\n", num);
rc = sendto(client_socket, my_buff, strlen(my_buff), 0, (struct sockaddr *) &remote,
sizeof(remote)); // send "num:x"
if (rc == -1) {
err = errno;
printf("SENDTO ERROR num = %d : %s", err, strerror(err));
close(client_socket);
// exit(1);
}
}
/***************************************/
if (!show_img) return;
static int frame_id = 0;
frame_id++;
for (i = 0; i < num; ++i) {
/*********** added by sakachan ***********/
char out_buff[4096] = { 0 };
/***************************************/
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);
/*********** added by sakachan ***********/
sprintf(my_str,"%s: %.0f%%", names[j], dets[i].prob[j] * 100);
strcat(out_buff, my_str);
/***************************************/
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);
/*********** added by sakachan ***********/
sprintf(my_str,",%s: %.0f%%", names[j], dets[i].prob[j] * 100);
strcat(out_buff, my_str);
/****************************/
}
}
}
if (class_id >= 0) {
int width = std::max(1.0f, show_img->rows * .002f);
//if(0){
//width = pow(prob, 1./2.)*10+1;
//alphabet = 0;
//}
//printf("%d %s: %.0f%%\n", i, names[class_id], prob*100);
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; /* uncomment by sakachan */
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);
// sprintf(labelstr, "x:%d y:%d w:%d h:%d", b_x_center, b_y_center, b_width, b_height); // modified by sakachan
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);
/****** added by sakachan ******/
sprintf(my_buff, ",c_x: %4.0f,c_y: %4.0f,w: %4.0f,h: %4.0f\n",
(float)b_x_center, (float)b_y_center, (float)b_width, (float)b_height);
strcat(out_buff, my_buff);
rc = sendto(client_socket, out_buff, strlen(out_buff), 0, (struct sockaddr *) &remote, sizeof(remote));
if (rc == -1) {
err = errno;
printf("SENDTO ERROR out = %d : %s", err, strerror(err));
// close(client_socket);
// exit(1);
}
} 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) {
/*****************************/
/* Close the socket and exit */
/*****************************/
rc = sendto(client_socket, end, strlen(end), 0, (struct sockaddr *) &remote,
sizeof(remote)); // send "E"
if (rc == -1) {
err = errno;
printf("SENDTO ERROR end = %d : %s", err, strerror(err));
// close(client_socket);
// exit(1);
}
rc = close(client_socket);
/*****************************/
fflush(stdout);
}
}
catch (...) {
cerr << "OpenCV exception: draw_detections_cv_v3() \n";
}
}
// ----------------------------------------
2. socket通信のサーバ側のプログラム(C#)
単純にdarknetからのsocket通信を受信するだけです。
あとは、受信したメッセージを加工して、利用することになります。
Server.cs
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Text;
using System.Collections.Generic;
using System.Net;
class Program
{
private static void Main(string[] args)
{
var unixSocket = "/tmp/foo.sock";
// delete file if it exists
if (System.IO.File.Exists(unixSocket))
System.IO.File.Delete(unixSocket);
// 接続ソケットの準備
Socket s = new Socket(AddressFamily.Unix, SocketType.Dgram, ProtocolType.Unspecified);
var unixEp = new UnixDomainSocketEndPoint(unixSocket);
System.IO.File.Delete(unixSocket);
s.Bind(unixEp);
Console.WriteLine("Server started waiting for client to connect...");
string message = "";
byte[] buffer = new byte[1024];
while (true)
{
int numberOfBytesReceived = s.Receive(buffer, 0, buffer.Length, SocketFlags.None);
if (numberOfBytesReceived <= 0)
{
break;
}
Console.WriteLine(numberOfBytesReceived);
message = System.Text.Encoding.UTF8.GetString(buffer, 0, numberOfBytesReceived);
Console.WriteLine(message);
}
s.Close();
}
}