Experimental. Use -json_port 8070 to allow connection to the port:8070 to get json-stream

pull/2179/head
AlexeyAB 6 years ago
parent ead84c8ba2
commit c31a245665
  1. 7
      build/darknet/x64/darknet_demo_json_stream.cmd
  2. 2
      build/darknet/x64/darknet_demo_mjpeg_stream.cmd
  3. 3
      include/darknet.h
  4. 5
      src/coco.c
  5. 13
      src/demo.c
  6. 3
      src/demo.h
  7. 3
      src/detector.c
  8. 161
      src/http_stream.cpp
  9. 1
      src/http_stream.h
  10. 38
      src/network.c
  11. 3
      src/yolo.c

@ -0,0 +1,7 @@
rem Run this file and then open URL in Chrome/Firefox: rem http://localhost:8070
rem Or open: http://ip-address:8070
darknet.exe detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights test.mp4 -i 0 -json_port 8070 -dont_show -ext_output
pause

@ -1,7 +1,7 @@
rem Run this file and then open URL in Chrome/Firefox: rem http://localhost:8090 rem Run this file and then open URL in Chrome/Firefox: rem http://localhost:8090
rem Or open: http://ip-address:8090 rem Or open: http://ip-address:8090
darknet.exe detector demo data/voc.data cfg/yolov2-voc.cfg yolo-voc.weights test.mp4 -i 0 -http_port 8090 -dont_show darknet.exe detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights test.mp4 -i 0 -http_port 8090 -dont_show -ext_output
pause pause

@ -744,9 +744,10 @@ LIB_API detection *get_network_boxes(network *net, int w, int h, float thresh, f
LIB_API void free_detections(detection *dets, int n); LIB_API void free_detections(detection *dets, int n);
LIB_API void fuse_conv_batchnorm(network net); LIB_API void fuse_conv_batchnorm(network net);
LIB_API void calculate_binary_weights(network net); LIB_API void calculate_binary_weights(network net);
LIB_API char *detection_to_json(detection *dets, int nboxes, int classes, char **names, long long int frame_id);
LIB_API layer* get_network_layer(network* net, int i); LIB_API layer* get_network_layer(network* net, int i);
LIB_API detection *get_network_boxes(network *net, int w, int h, float thresh, float hier, int *map, int relative, int *num, int letter); //LIB_API detection *get_network_boxes(network *net, int w, int h, float thresh, float hier, int *map, int relative, int *num, int letter);
LIB_API detection *make_network_boxes(network *net, float thresh, int *num); LIB_API detection *make_network_boxes(network *net, float thresh, int *num);
LIB_API void reset_rnn(network *net); LIB_API void reset_rnn(network *net);
LIB_API float *network_predict_image(network *net, image im); LIB_API float *network_predict_image(network *net, image im);

@ -222,7 +222,7 @@ void validate_coco(char *cfgfile, char *weightfile)
free_image(val_resized[t]); free_image(val_resized[t]);
} }
} }
fseek(fp, -2, SEEK_CUR); fseek(fp, -2, SEEK_CUR);
fprintf(fp, "\n]\n"); fprintf(fp, "\n]\n");
fclose(fp); fclose(fp);
@ -366,6 +366,7 @@ void run_coco(int argc, char **argv)
{ {
int dont_show = find_arg(argc, argv, "-dont_show"); int dont_show = find_arg(argc, argv, "-dont_show");
int http_stream_port = find_int_arg(argc, argv, "-http_port", -1); int http_stream_port = find_int_arg(argc, argv, "-http_port", -1);
int json_port = find_int_arg(argc, argv, "-json_port", -1);
char *out_filename = find_char_arg(argc, argv, "-out_filename", 0); char *out_filename = find_char_arg(argc, argv, "-out_filename", 0);
char *prefix = find_char_arg(argc, argv, "-prefix", 0); char *prefix = find_char_arg(argc, argv, "-prefix", 0);
float thresh = find_float_arg(argc, argv, "-thresh", .2); float thresh = find_float_arg(argc, argv, "-thresh", .2);
@ -387,5 +388,5 @@ void run_coco(int argc, char **argv)
else if(0==strcmp(argv[2], "valid")) validate_coco(cfg, weights); else if(0==strcmp(argv[2], "valid")) validate_coco(cfg, weights);
else if(0==strcmp(argv[2], "recall")) validate_coco_recall(cfg, weights); else if(0==strcmp(argv[2], "recall")) validate_coco_recall(cfg, weights);
else if(0==strcmp(argv[2], "demo")) demo(cfg, weights, thresh, hier_thresh, cam_index, filename, coco_classes, 80, frame_skip, else if(0==strcmp(argv[2], "demo")) demo(cfg, weights, thresh, hier_thresh, cam_index, filename, coco_classes, 80, frame_skip,
prefix, out_filename, http_stream_port, dont_show, ext_output); prefix, out_filename, http_stream_port, json_port, dont_show, ext_output);
} }

@ -41,6 +41,8 @@ static int cpp_video_capture = 0;
static float fps = 0; static float fps = 0;
static float demo_thresh = 0; static float demo_thresh = 0;
static int demo_ext_output = 0; static int demo_ext_output = 0;
static long long int frame_id = 0;
static int demo_json_port = -1;
static float *predictions[FRAMES]; static float *predictions[FRAMES];
static int demo_index = 0; static int demo_index = 0;
@ -114,6 +116,12 @@ void *detect_in_thread(void *ptr)
det_img = ipl_images[(demo_index + FRAMES / 2 + 1) % FRAMES]; det_img = ipl_images[(demo_index + FRAMES / 2 + 1) % FRAMES];
demo_index = (demo_index + 1)%FRAMES; demo_index = (demo_index + 1)%FRAMES;
++frame_id;
if (demo_json_port > 0) {
int timeout = 200;
send_json(dets, nboxes, l.classes, demo_names, frame_id, demo_json_port, timeout);
}
draw_detections_cv_v3(det_img, dets, nboxes, demo_thresh, demo_names, demo_alphabet, demo_classes, demo_ext_output); draw_detections_cv_v3(det_img, dets, nboxes, demo_thresh, demo_names, demo_alphabet, demo_classes, demo_ext_output);
free_detections(dets, nboxes); free_detections(dets, nboxes);
@ -130,7 +138,7 @@ double get_wall_time()
} }
void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int cam_index, const char *filename, char **names, int classes, void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int cam_index, const char *filename, char **names, int classes,
int frame_skip, char *prefix, char *out_filename, int http_stream_port, int dont_show, int ext_output) int frame_skip, char *prefix, char *out_filename, int http_stream_port, int json_port, int dont_show, int ext_output)
{ {
//skip = frame_skip; //skip = frame_skip;
image **alphabet = load_alphabet(); image **alphabet = load_alphabet();
@ -140,6 +148,7 @@ void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int
demo_classes = classes; demo_classes = classes;
demo_thresh = thresh; demo_thresh = thresh;
demo_ext_output = ext_output; demo_ext_output = ext_output;
demo_json_port = json_port;
printf("Demo\n"); printf("Demo\n");
net = parse_network_cfg_custom(cfgfile, 1); // set batch=1 net = parse_network_cfg_custom(cfgfile, 1); // set batch=1
if(weightfile){ if(weightfile){
@ -355,7 +364,7 @@ void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int
} }
#else #else
void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int cam_index, const char *filename, char **names, int classes, void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int cam_index, const char *filename, char **names, int classes,
int frame_skip, char *prefix, char *out_filename, int http_stream_port, int dont_show, int ext_output) int frame_skip, char *prefix, char *out_filename, int http_stream_port, int json_port, int dont_show, int ext_output)
{ {
fprintf(stderr, "Demo needs OpenCV for webcam images.\n"); fprintf(stderr, "Demo needs OpenCV for webcam images.\n");
} }

@ -2,6 +2,7 @@
#define DEMO #define DEMO
#include "image.h" #include "image.h"
void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int cam_index, const char *filename, char **names, int classes, int frame_skip, char *prefix, char *out_filename, int http_stream_port, int dont_show, int ext_output); void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int cam_index, const char *filename, char **names, int classes,
int frame_skip, char *prefix, char *out_filename, int http_stream_port, int json_port, int dont_show, int ext_output);
#endif #endif

@ -1352,6 +1352,7 @@ void run_detector(int argc, char **argv)
int calc_map = find_arg(argc, argv, "-map"); int calc_map = find_arg(argc, argv, "-map");
check_mistakes = find_arg(argc, argv, "-check_mistakes"); check_mistakes = find_arg(argc, argv, "-check_mistakes");
int http_stream_port = find_int_arg(argc, argv, "-http_port", -1); int http_stream_port = find_int_arg(argc, argv, "-http_port", -1);
int json_port = find_int_arg(argc, argv, "-json_port", -1);
char *out_filename = find_char_arg(argc, argv, "-out_filename", 0); char *out_filename = find_char_arg(argc, argv, "-out_filename", 0);
char *outfile = find_char_arg(argc, argv, "-out", 0); char *outfile = find_char_arg(argc, argv, "-out", 0);
char *prefix = find_char_arg(argc, argv, "-prefix", 0); char *prefix = find_char_arg(argc, argv, "-prefix", 0);
@ -1419,7 +1420,7 @@ void run_detector(int argc, char **argv)
if (strlen(filename) > 0) if (strlen(filename) > 0)
if (filename[strlen(filename) - 1] == 0x0d) filename[strlen(filename) - 1] = 0; if (filename[strlen(filename) - 1] == 0x0d) filename[strlen(filename) - 1] = 0;
demo(cfg, weights, thresh, hier_thresh, cam_index, filename, names, classes, frame_skip, prefix, out_filename, demo(cfg, weights, thresh, hier_thresh, cam_index, filename, names, classes, frame_skip, prefix, out_filename,
http_stream_port, dont_show, ext_output); http_stream_port, json_port, dont_show, ext_output);
free_list_contents_kvp(options); free_list_contents_kvp(options);
free_list(options); free_list(options);

@ -196,7 +196,8 @@ public:
}; };
// ---------------------------------------- // ----------------------------------------
void send_mjpeg(IplImage* ipl, int port, int timeout, int quality) { void send_mjpeg(IplImage* ipl, int port, int timeout, int quality)
{
static MJPGWriter wri(port, timeout, quality); static MJPGWriter wri(port, timeout, quality);
cv::Mat mat = cv::cvarrToMat(ipl); cv::Mat mat = cv::cvarrToMat(ipl);
wri.write(mat); wri.write(mat);
@ -204,6 +205,164 @@ void send_mjpeg(IplImage* ipl, int port, int timeout, int quality) {
} }
// ---------------------------------------- // ----------------------------------------
class JSON_sender
{
SOCKET sock;
SOCKET maxfd;
fd_set master;
int timeout; // master sock timeout, shutdown after timeout millis.
int _write(int sock, char const*const s, int len)
{
if (len < 1) { len = strlen(s); }
return ::send(sock, s, len, 0);
}
public:
JSON_sender(int port = 0, int _timeout = 200000)
: sock(INVALID_SOCKET)
, timeout(_timeout)
{
FD_ZERO(&master);
if (port)
open(port);
}
~JSON_sender()
{
release();
}
bool release()
{
if (sock != INVALID_SOCKET)
::shutdown(sock, 2);
sock = (INVALID_SOCKET);
return false;
}
bool open(int port)
{
sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN address;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_family = AF_INET;
address.sin_port = htons(port); // ::htons(port);
if (::bind(sock, (SOCKADDR*)&address, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
cerr << "error : couldn't bind sock " << sock << " to port " << port << "!" << endl;
return release();
}
if (::listen(sock, 10) == SOCKET_ERROR)
{
cerr << "error : couldn't listen on sock " << sock << " on port " << port << " !" << endl;
return release();
}
FD_ZERO(&master);
FD_SET(sock, &master);
maxfd = sock;
return true;
}
bool isOpened()
{
return sock != INVALID_SOCKET;
}
bool write(char *outputbuf)
{
fd_set rread = master;
struct timeval to = { 0,timeout };
if (::select(maxfd + 1, &rread, NULL, NULL, &to) <= 0)
return true; // nothing broken, there's just noone listening
size_t outlen = strlen(outputbuf);
#ifdef _WIN32
for (unsigned i = 0; i<rread.fd_count; i++)
{
int addrlen = sizeof(SOCKADDR);
SOCKET s = rread.fd_array[i]; // fd_set on win is an array, while ...
#else
for (int s = 0; s <= maxfd; s++)
{
socklen_t addrlen = sizeof(SOCKADDR);
if (!FD_ISSET(s, &rread)) // ... on linux it's a bitmask ;)
continue;
#endif
if (s == sock) // request on master socket, accept and send main header.
{
SOCKADDR_IN address = { 0 };
SOCKET client = ::accept(sock, (SOCKADDR*)&address, &addrlen);
if (client == SOCKET_ERROR)
{
cerr << "error : couldn't accept connection on sock " << sock << " !" << endl;
return false;
}
maxfd = (maxfd>client ? maxfd : client);
FD_SET(client, &master);
_write(client, "HTTP/1.0 200 OK\r\n", 0);
_write(client,
"Server: Mozarella/2.2\r\n"
"Accept-Range: bytes\r\n"
"Connection: close\r\n"
"Max-Age: 0\r\n"
"Expires: 0\r\n"
"Cache-Control: no-cache, private\r\n"
"Pragma: no-cache\r\n"
"Content-Type: application/json\r\n"
//"Content-Type: multipart/x-mixed-replace; boundary=boundary\r\n"
"\r\n", 0);
cerr << "new client " << client << endl;
}
else // existing client, just stream pix
{
char head[400];
// application/json
// application/x-resource+json or application/x-collection+json - when you are representing REST resources and collections
// text/json or text/javascript or text/plain.
// https://stackoverflow.com/questions/477816/what-is-the-correct-json-content-type
//sprintf(head, "\r\nContent-Length: %zu\r\n\r\n", outlen);
//sprintf(head, "--boundary\r\nContent-Type: application/json\r\nContent-Length: %zu\r\n\r\n", outlen);
_write(s, head, 0);
int n = _write(s, outputbuf, outlen);
//cerr << "known client " << s << " " << n << endl;
if (n < outlen)
{
cerr << "kill client " << s << endl;
::shutdown(s, 2);
FD_CLR(s, &master);
}
}
}
return true;
}
};
// ----------------------------------------
// JSON format:
//{
// "frame_id":8990,
// "objects":[
// {"class_id":4, "name":"aeroplane", "relative coordinates":{"center_x":0.398831, "center_y":0.630203, "width":0.057455, "height":0.020396}, "confidence":0.793070},
// {"class_id":14, "name":"bird", "relative coordinates":{"center_x":0.398831, "center_y":0.630203, "width":0.057455, "height":0.020396}, "confidence":0.265497}
// ]
//},
void send_json(detection *dets, int nboxes, int classes, char **names, long long int frame_id, int port, int timeout)
{
static JSON_sender js(port, timeout);
char *send_buf = detection_to_json(dets, nboxes, classes, names, frame_id);
js.write(send_buf);
std::cout << " JSON-stream sent. \n";
free(send_buf);
}
// ----------------------------------------
CvCapture* get_capture_video_stream(char *path) { CvCapture* get_capture_video_stream(char *path) {
CvCapture* cap = NULL; CvCapture* cap = NULL;
try { try {

@ -15,6 +15,7 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#ifdef OPENCV #ifdef OPENCV
void send_json(detection *dets, int nboxes, int classes, char **names, long long int frame_id, int port, int timeout);
void send_mjpeg(IplImage* ipl, int port, int timeout, int quality); void send_mjpeg(IplImage* ipl, int port, int timeout, int quality);
CvCapture* get_capture_webcam(int index); CvCapture* get_capture_webcam(int index);
CvCapture* get_capture_video_stream(char *path); CvCapture* get_capture_video_stream(char *path);

@ -658,6 +658,44 @@ void free_detections(detection *dets, int n)
free(dets); free(dets);
} }
char *detection_to_json(detection *dets, int nboxes, int classes, char **names, long long int frame_id)
{
const float thresh = 0.005; // function get_network_boxes() has already filtred dets by actual threshold
char *send_buf = (char *)calloc(1024, sizeof(char));
sprintf(send_buf, "{\n \"frame_id\":%d, \n \"objects\":[ \n", frame_id);
int i, j;
int class_id = -1;
for (i = 0; i < nboxes; ++i) {
for (j = 0; j < classes; ++j) {
int show = strncmp(names[j], "dont_show", 9);
if (dets[i].prob[j] > thresh && show)
{
if (class_id != -1) strcat(send_buf, ", \n");
class_id = j;
char *buf = (char *)calloc(2048, sizeof(char));
//sprintf(buf, "{\"image_id\":%d, \"category_id\":%d, \"bbox\":[%f, %f, %f, %f], \"score\":%f}",
// image_id, j, dets[i].bbox.x, dets[i].bbox.y, dets[i].bbox.w, dets[i].bbox.h, dets[i].prob[j]);
sprintf(buf, " {\"class_id\":%d, \"name\":\"%s\", \"relative coordinates\":{\"center_x\":%f, \"center_y\":%f, \"width\":%f, \"height\":%f}, \"confidence\":%f}",
j, names[j], dets[i].bbox.x, dets[i].bbox.y, dets[i].bbox.w, dets[i].bbox.h, dets[i].prob[j]);
int send_buf_len = strlen(send_buf);
int buf_len = strlen(buf);
int total_len = send_buf_len + buf_len + 100;
send_buf = (char *)realloc(send_buf, total_len * sizeof(char));
if (!send_buf) return;// exit(-1);
strcat(send_buf, buf);
free(buf);
}
}
}
strcat(send_buf, "\n ] \n}, \n");
return send_buf;
}
float *network_predict_image(network *net, image im) float *network_predict_image(network *net, image im)
{ {
//image imr = letterbox_image(im, net->w, net->h); //image imr = letterbox_image(im, net->w, net->h);

@ -339,6 +339,7 @@ void run_yolo(int argc, char **argv)
{ {
int dont_show = find_arg(argc, argv, "-dont_show"); int dont_show = find_arg(argc, argv, "-dont_show");
int http_stream_port = find_int_arg(argc, argv, "-http_port", -1); int http_stream_port = find_int_arg(argc, argv, "-http_port", -1);
int json_port = find_int_arg(argc, argv, "-json_port", -1);
char *out_filename = find_char_arg(argc, argv, "-out_filename", 0); char *out_filename = find_char_arg(argc, argv, "-out_filename", 0);
char *prefix = find_char_arg(argc, argv, "-prefix", 0); char *prefix = find_char_arg(argc, argv, "-prefix", 0);
float thresh = find_float_arg(argc, argv, "-thresh", .2); float thresh = find_float_arg(argc, argv, "-thresh", .2);
@ -359,5 +360,5 @@ void run_yolo(int argc, char **argv)
else if(0==strcmp(argv[2], "valid")) validate_yolo(cfg, weights); else if(0==strcmp(argv[2], "valid")) validate_yolo(cfg, weights);
else if(0==strcmp(argv[2], "recall")) validate_yolo_recall(cfg, weights); else if(0==strcmp(argv[2], "recall")) validate_yolo_recall(cfg, weights);
else if(0==strcmp(argv[2], "demo")) demo(cfg, weights, thresh, hier_thresh, cam_index, filename, voc_names, 20, frame_skip, else if(0==strcmp(argv[2], "demo")) demo(cfg, weights, thresh, hier_thresh, cam_index, filename, voc_names, 20, frame_skip,
prefix, out_filename, http_stream_port, dont_show, ext_output); prefix, out_filename, http_stream_port, json_port, dont_show, ext_output);
} }

Loading…
Cancel
Save