diff --git a/data/dogs/Airedale, Airedale terrier.jpg b/data/dogs/Airedale, Airedale terrier.jpg new file mode 100644 index 0000000..bea5e15 Binary files /dev/null and b/data/dogs/Airedale, Airedale terrier.jpg differ diff --git a/data/dogs/Australian terrier.jpg b/data/dogs/Australian terrier.jpg new file mode 100644 index 0000000..3a2968c Binary files /dev/null and b/data/dogs/Australian terrier.jpg differ diff --git a/data/dogs/Chihuahua.jpg b/data/dogs/Chihuahua.jpg new file mode 100644 index 0000000..b53bb3e Binary files /dev/null and b/data/dogs/Chihuahua.jpg differ diff --git a/data/dogs/Doberman, Doberman pinscher.jpg b/data/dogs/Doberman, Doberman pinscher.jpg new file mode 100644 index 0000000..d8f8afa Binary files /dev/null and b/data/dogs/Doberman, Doberman pinscher.jpg differ diff --git a/data/dogs/English foxhound.jpg b/data/dogs/English foxhound.jpg new file mode 100644 index 0000000..c457d6b Binary files /dev/null and b/data/dogs/English foxhound.jpg differ diff --git a/data/dogs/Eskimo dog, husky.jpg b/data/dogs/Eskimo dog, husky.jpg new file mode 100644 index 0000000..00209aa Binary files /dev/null and b/data/dogs/Eskimo dog, husky.jpg differ diff --git a/data/dogs/French bulldog.jpg b/data/dogs/French bulldog.jpg new file mode 100644 index 0000000..69c6ec1 Binary files /dev/null and b/data/dogs/French bulldog.jpg differ diff --git a/data/dogs/German short-haired pointer.jpg b/data/dogs/German short-haired pointer.jpg new file mode 100644 index 0000000..4637fcc Binary files /dev/null and b/data/dogs/German short-haired pointer.jpg differ diff --git a/data/dogs/Ibizan hound, Ibizan Podenco.jpg b/data/dogs/Ibizan hound, Ibizan Podenco.jpg new file mode 100644 index 0000000..43e783a Binary files /dev/null and b/data/dogs/Ibizan hound, Ibizan Podenco.jpg differ diff --git a/data/dogs/Maltese dog, Maltese terrier, Maltese.jpg b/data/dogs/Maltese dog, Maltese terrier, Maltese.jpg new file mode 100644 index 0000000..d82b62f Binary files /dev/null and b/data/dogs/Maltese dog, Maltese terrier, Maltese.jpg differ diff --git a/data/dogs/Mexican hairless.jpg b/data/dogs/Mexican hairless.jpg new file mode 100644 index 0000000..57a8468 Binary files /dev/null and b/data/dogs/Mexican hairless.jpg differ diff --git a/data/dogs/Newfoundland, Newfoundland dog.jpg b/data/dogs/Newfoundland, Newfoundland dog.jpg new file mode 100644 index 0000000..548ac88 Binary files /dev/null and b/data/dogs/Newfoundland, Newfoundland dog.jpg differ diff --git a/data/dogs/Pomeranian.jpg b/data/dogs/Pomeranian.jpg new file mode 100644 index 0000000..7c23c28 Binary files /dev/null and b/data/dogs/Pomeranian.jpg differ diff --git a/data/dogs/Rottweiler.jpg b/data/dogs/Rottweiler.jpg new file mode 100644 index 0000000..0bff5b4 Binary files /dev/null and b/data/dogs/Rottweiler.jpg differ diff --git a/data/dogs/Saint Bernard, St Bernard.jpg b/data/dogs/Saint Bernard, St Bernard.jpg new file mode 100644 index 0000000..fbba651 Binary files /dev/null and b/data/dogs/Saint Bernard, St Bernard.jpg differ diff --git a/data/dogs/Samoyed, Samoyede.jpg b/data/dogs/Samoyed, Samoyede.jpg new file mode 100644 index 0000000..a5e0040 Binary files /dev/null and b/data/dogs/Samoyed, Samoyede.jpg differ diff --git a/data/dogs/Sealyham terrier, Sealyham.jpg b/data/dogs/Sealyham terrier, Sealyham.jpg new file mode 100644 index 0000000..ba2c38c Binary files /dev/null and b/data/dogs/Sealyham terrier, Sealyham.jpg differ diff --git a/data/dogs/Weimaraner.jpg b/data/dogs/Weimaraner.jpg new file mode 100644 index 0000000..b9629bf Binary files /dev/null and b/data/dogs/Weimaraner.jpg differ diff --git a/data/dogs/basenji.jpg b/data/dogs/basenji.jpg new file mode 100644 index 0000000..777ed7b Binary files /dev/null and b/data/dogs/basenji.jpg differ diff --git a/data/dogs/boxer.jpg b/data/dogs/boxer.jpg new file mode 100644 index 0000000..5398919 Binary files /dev/null and b/data/dogs/boxer.jpg differ diff --git a/data/dogs/bull mastiff.jpg b/data/dogs/bull mastiff.jpg new file mode 100644 index 0000000..702f8f1 Binary files /dev/null and b/data/dogs/bull mastiff.jpg differ diff --git a/data/dogs/chow, chow chow.jpg b/data/dogs/chow, chow chow.jpg new file mode 100644 index 0000000..d7b2136 Binary files /dev/null and b/data/dogs/chow, chow chow.jpg differ diff --git a/data/dogs/collie.jpg b/data/dogs/collie.jpg new file mode 100644 index 0000000..05f64fe Binary files /dev/null and b/data/dogs/collie.jpg differ diff --git a/data/dogs/dalmatian, coach dog, carriage dog.jpg b/data/dogs/dalmatian, coach dog, carriage dog.jpg new file mode 100644 index 0000000..808a29a Binary files /dev/null and b/data/dogs/dalmatian, coach dog, carriage dog.jpg differ diff --git a/data/dogs/dingo, warrigal, warragal, Canis dingo.jpg b/data/dogs/dingo, warrigal, warragal, Canis dingo.jpg new file mode 100644 index 0000000..9546df5 Binary files /dev/null and b/data/dogs/dingo, warrigal, warragal, Canis dingo.jpg differ diff --git a/data/dogs/miniature schnauzer.jpg b/data/dogs/miniature schnauzer.jpg new file mode 100644 index 0000000..b07343b Binary files /dev/null and b/data/dogs/miniature schnauzer.jpg differ diff --git a/data/dogs/pug, pug-dog.jpg b/data/dogs/pug, pug-dog.jpg new file mode 100644 index 0000000..d292e62 Binary files /dev/null and b/data/dogs/pug, pug-dog.jpg differ diff --git a/data/dogs/redbone.jpg b/data/dogs/redbone.jpg new file mode 100644 index 0000000..e0f864d Binary files /dev/null and b/data/dogs/redbone.jpg differ diff --git a/data/dogs/standard schnauzer.jpg b/data/dogs/standard schnauzer.jpg new file mode 100644 index 0000000..a679abd Binary files /dev/null and b/data/dogs/standard schnauzer.jpg differ diff --git a/data/dogs/white wolf, Arctic wolf, Canis lupus tundrarum.jpg b/data/dogs/white wolf, Arctic wolf, Canis lupus tundrarum.jpg new file mode 100644 index 0000000..d960e5c Binary files /dev/null and b/data/dogs/white wolf, Arctic wolf, Canis lupus tundrarum.jpg differ diff --git a/data/dogs/wire-haired fox terrier.jpg b/data/dogs/wire-haired fox terrier.jpg new file mode 100644 index 0000000..6c034c2 Binary files /dev/null and b/data/dogs/wire-haired fox terrier.jpg differ diff --git a/include/classificator.h b/include/classificator.h index bb336c1..92fcf29 100644 --- a/include/classificator.h +++ b/include/classificator.h @@ -16,4 +16,28 @@ class Classificator public: vector classesNames; virtual Mat Classify(Mat image) = 0 {} +}; + + + +class DnnClassificator :Classificator +{ +private: + string model, config, labels; + int width, height, swapRB; + Scalar mean; + Net net; + int backendId; + int targetId; + Mat blob; + double scale; + int ddepth; + bool crop; + + +public: + DnnClassificator(string pthModel, string pthConfig, string pthLabels, int inputWidth, int inputHeight, + Scalar myMean = (0, 0, 0, 0), int mySwapRB = 0); + virtual Mat Classify(Mat image); + }; \ No newline at end of file diff --git a/samples/practice1_PEROV_DIMA.cpp b/samples/practice1_PEROV_DIMA.cpp new file mode 100644 index 0000000..92af778 --- /dev/null +++ b/samples/practice1_PEROV_DIMA.cpp @@ -0,0 +1,58 @@ +#include +#include + +#include +#include + +#include "filter.h" + +using namespace cv; +using namespace std; + +const char* cmdAbout = "Sample of OpenCV usage. "; + +const char* cmdOptions = +"{ i image | | image to process }" +"{ w width | | width for image resize }" +"{ h height | | height for image resize }" +"{ q ? help usage | | print help message }"; + +int main(int argc, char** argv) +{ + // Process input arguments + CommandLineParser parser(argc, argv, cmdOptions); + parser.about(cmdAbout); + + if (parser.has("help")) + { + parser.printMessage(); + return 0; + } + if (!parser.check()) + { + parser.printErrors(); + return 0; + } + + // Load image + String imgName(parser.get("image")); + Mat image = imread(imgName); + Mat res(image.size(), CV_8UC3); + Mat res1(image.size(), CV_8UC1); + + // Filter image + + GrayFilter myFilter; + ResizeFilter myResizeFilter(parser.get("width"), parser.get("height")); + + res = myResizeFilter.ProcessImage(image); + res1 = myFilter.ProcessImage(res); + + // Show image + + imwrite("res.jpg", res1); + imshow("image", res1); + waitKey(); + + return 0; +} diff --git a/samples/practice2_PEROV_DIMA.cpp b/samples/practice2_PEROV_DIMA.cpp new file mode 100644 index 0000000..115a257 --- /dev/null +++ b/samples/practice2_PEROV_DIMA.cpp @@ -0,0 +1,101 @@ +#include +#include +#include + +#include +#include + +#include "classificator.h" + +using namespace cv; +using namespace std; + +const char* cmdAbout = "Sample of OpenCV usage. "; + +const char* cmdOptions = +"{ i image | | image to process }" +"{ w width | | image width for classification }" +"{ h heigth | | image heigth fro classification }" +"{ model_path | | path to model }" +"{ config_path | | path to model configuration }" +"{ label_path | | path to class labels }" +"{ mean | | vector of mean model values }" +"{ swap | | swap R and B channels. TRUE|FALSE }" +"{ q ? help usage | | print help message }"; + +int main(int argc, char** argv) +{ + // Process input arguments + CommandLineParser parser(argc, argv, cmdOptions); + parser.about(cmdAbout); + + if (parser.has("help")) + { + parser.printMessage(); + return 0; + } + if (!parser.check()) + { + parser.printErrors(); + return 0; + } + + // Load image and init parameters + String imgName(parser.get("image")); + String model_path(parser.get("model_path")); + String config_path(parser.get("config_path")); + String path_label(parser.get("label_path")); + int width(parser.get("width")); + int height(parser.get("heigth")); + Scalar mean(parser.get("mean")); + int swapRB(parser.get("swap")); + + DnnClassificator dnn(model_path, config_path, + path_label, width , height, mean, swapRB); + + Mat image = imread(imgName); + Mat prob; + //Image classification + + prob = dnn.Classify(image); + + //Show result + Point classIdPoint; + double confidence; + minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint); + + int classId = classIdPoint.x; + + std::cout << "Class: " << classId << '\n'; + std::cout << "Confidence: " << confidence << '\n'; + + std::string name; + + std::ifstream in("../../CV-SUMMER-CAMP/data/squeezenet1.1.labels"); + int count = 0; + if (in.is_open()) + { + while (getline(in, name)) + { + if (count == classId) + { + break; + } + count++; + + } + } + in.close(); + + + + Mat res = image; + putText(res, "Class: "+to_string(classId), Point(30, 30), FONT_HERSHEY_COMPLEX_SMALL, 0.8, Scalar(200, 200, 250)); + putText(res, "Confidence: " + to_string(confidence), Point(30, 60), FONT_HERSHEY_COMPLEX_SMALL, 0.8, Scalar(200, 200, 250)); + putText(res, name, Point(30, 90), FONT_HERSHEY_COMPLEX_SMALL, 0.8, Scalar(200, 200, 250)); + + + imshow("image", res); + waitKey(); + return 0; +} diff --git a/samples/practice5 _PEROV_DIMA.cpp b/samples/practice5 _PEROV_DIMA.cpp new file mode 100644 index 0000000..dc9c581 --- /dev/null +++ b/samples/practice5 _PEROV_DIMA.cpp @@ -0,0 +1,339 @@ +#include +#include +#include +#include +#include "tracking_by_matching.hpp" +#include + + +using namespace std; +using namespace cv; +using namespace cv::tbm; + +static const char* keys = +{ "{video_name | | video name }" +"{start_frame |0| Start frame }" +"{frame_step |2| Frame step }" +"{detector_model | | Path to detector's Caffe model }" +"{detector_weights | | Path to detector's Caffe weights }" +"{desired_class_id |12| The desired class that should be tracked }" +"{ w width |227| image width for classification }" +"{ h heigth |227| image heigth fro classification }" +"{ model_path |C:/Users/temp2019/Documents/GitHub/CV-SUMMER-CAMP-build1/data/classification/squeezenet/1.1/caffe/squeezenet1.1.caffemodel|}" +"{ config_path |C:/Users/temp2019/Documents/GitHub/CV-SUMMER-CAMP-build1/data/classification/squeezenet/1.1/caffe/squeezenet1.1.prototxt| path to model configuration}" +"{ label_path | | path to class labels }" +"{ mean |""104.0 117.0 123.0""| vector of mean model values }" +"{ swap |FALSE| swap R and B channels. TRUE|FALSE }" +}; + + + + + + +static void help() +{ + cout << "\nThis example shows the functionality of \"Tracking-by-Matching\" approach:" + " detector is used to detect objects on frames, \n" + "matching is used to find correspondences between new detections and tracked objects.\n" + "Detection is made by DNN detection network every `--frame_step` frame.\n" + "Point a .prototxt file of the network as the parameter `--detector_model`, and a .caffemodel file" + " as the parameter `--detector_weights`.\n" + "(As an example of such detection network is a popular MobileNet_SSD network trained on VOC dataset.)\n" + "If `--desired_class_id` parameter is set, the detection result is filtered by class id," + " returned by the detection network.\n" + "(That is, if a detection net was trained on VOC dataset, then to track pedestrians point --desired_class_id=15)\n" + "Example of is in opencv_extra/testdata/cv/tracking/\n" + "Call:\n" + "./example_tracking_tracking_by_matching --video_name= --detector_model= --detector_weights= \\\n" + " [--start_frame=] \\\n" + " [--frame_step=] \\\n" + " [--desired_class_id=]\n" + << endl; + + cout << "\n\nHot keys: \n" + "\tq - quit the program\n" + "\tp - pause/resume video\n"; +} + +cv::Ptr createTrackerByMatchingWithFastDescriptor(); + +class DnnObjectDetector +{ +public: + DnnObjectDetector(const String& net_caffe_model_path, const String& net_caffe_weights_path, + int desired_class_id = -1, + float confidence_threshold = 0.2, + //the following parameters are default for popular MobileNet_SSD caffe model + const String& net_input_name = "data", + const String& net_output_name = "detection_out", + double net_scalefactor = 0.007843, + const Size& net_size = Size(300, 300), + const Scalar& net_mean = Scalar(127.5, 127.5, 127.5), + bool net_swapRB = false) + :desired_class_id(desired_class_id), + confidence_threshold(confidence_threshold), + net_input_name(net_input_name), + net_output_name(net_output_name), + net_scalefactor(net_scalefactor), + net_size(net_size), + net_mean(net_mean), + net_swapRB(net_swapRB) + { + net = dnn::readNet(net_caffe_model_path, net_caffe_weights_path); + if (net.empty()) + CV_Error(Error::StsError, "Cannot read Caffe net"); + } + vector classid; + TrackedObjects detect(const cv::Mat& frame, int frame_idx) + { + Mat resized_frame; + resize(frame, resized_frame, net_size); + Mat inputBlob = cv::dnn::blobFromImage(resized_frame, net_scalefactor, net_size, net_mean, net_swapRB); + + net.setInput(inputBlob, net_input_name); + Mat detection = net.forward(net_output_name); + Mat detection_as_mat(detection.size[2], detection.size[3], CV_32F, detection.ptr()); + + TrackedObjects res; + for (int i = 0; i < detection_as_mat.rows; i++) + { + float cur_confidence = detection_as_mat.at(i, 2); + int cur_class_id = static_cast(detection_as_mat.at(i, 1)); + int x_left = static_cast(detection_as_mat.at(i, 3) * frame.cols); + int y_bottom = static_cast(detection_as_mat.at(i, 4) * frame.rows); + int x_right = static_cast(detection_as_mat.at(i, 5) * frame.cols); + int y_top = static_cast(detection_as_mat.at(i, 6) * frame.rows); + + Rect cur_rect(x_left, y_bottom, (x_right - x_left), (y_top - y_bottom)); + + if (cur_confidence < confidence_threshold) + continue; + if ((desired_class_id >= 0) && (cur_class_id != desired_class_id)) + continue; + + //clipping by frame size + cur_rect = cur_rect & Rect(Point(), frame.size()); + if (cur_rect.empty()) + continue; + + TrackedObject cur_obj(cur_rect, cur_confidence, frame_idx, -1); + res.push_back(cur_obj); + classid.push_back(cur_class_id); + } + + return res; + } +private: + cv::dnn::Net net; + int desired_class_id; + float confidence_threshold; + String net_input_name; + String net_output_name; + double net_scalefactor; + Size net_size; + Scalar net_mean; + bool net_swapRB; + +}; + +cv::Ptr +createTrackerByMatchingWithFastDescriptor() { + cv::tbm::TrackerParams params; + + cv::Ptr tracker = createTrackerByMatching(params); + + std::shared_ptr descriptor_fast = + std::make_shared( + cv::Size(16, 32), cv::InterpolationFlags::INTER_LINEAR); + std::shared_ptr distance_fast = + std::make_shared(); + + tracker->setDescriptorFast(descriptor_fast); + tracker->setDistanceFast(distance_fast); + + return tracker; +} + +int main(int argc, char** argv) { + + + int unic = 0; + CommandLineParser parser(argc, argv, keys); + cv::Ptr tracker = createTrackerByMatchingWithFastDescriptor(); + + String video_name = parser.get("video_name"); + int start_frame = parser.get("start_frame"); + int frame_step = parser.get("frame_step"); + String detector_model = parser.get("detector_model"); + String detector_weights = parser.get("detector_weights"); + int desired_class_id = parser.get("desired_class_id"); + + if (video_name.empty() || detector_model.empty() || detector_weights.empty()) + { + help(); + return -1; + } + + //open the capture + VideoCapture cap; + cap.open(video_name); + cap.set(CAP_PROP_POS_FRAMES, start_frame); + + if (!cap.isOpened()) + { + help(); + cout << "***Could not initialize capturing...***\n"; + cout << "Current parameter's value: \n"; + parser.printMessage(); + return -1; + } + + // If you use the popular MobileNet_SSD detector, the default parameters may be used. + // Otherwise, set your own parameters (net_mean, net_scalefactor, etc). + DnnObjectDetector detector(detector_model, detector_weights, desired_class_id); + + Mat frame; + namedWindow("Tracking by Matching", 1); + + int frame_counter = -1; + int64 time_total = 0; + bool paused = false; + for (;; ) + { + if (paused) + { + char c = (char)waitKey(30); + if (c == 'p') + paused = !paused; + if (c == 'q') + break; + continue; + } + + cap >> frame; + if (frame.empty()) { + break; + } + frame_counter++; + if (frame_counter < start_frame) + continue; + if (frame_counter % frame_step != 0) + continue; + + + int64 frame_time = getTickCount(); + + TrackedObjects detections = detector.detect(frame, frame_counter); + + // timestamp in milliseconds + uint64_t cur_timestamp = static_cast(1000.0 / 30 * frame_counter); + tracker->process(frame, detections, cur_timestamp); + + frame_time = getTickCount() - frame_time; + time_total += frame_time; + + // Drawing colored "worms" (tracks). + // frame = tracker->drawActiveTracks(frame); + + + // Drawing all detected objects on a frame by BLUE COLOR + for (const auto &detection : detections) { + cv::rectangle(frame, detection.rect, cv::Scalar(255, 0, 0), 1); + } + + + // Drawing tracked detections only by RED color and print ID and detection + // confidence level. + + + + + + for (const auto &detection : tracker->trackedDetections()) { + cv::rectangle(frame, detection.rect, cv::Scalar(0, 255, 0), 1); + std::string text = std::to_string(detection.object_id) + " " + + std::to_string(detection.confidence); + cv::putText(frame, text, detection.rect.tl(), cv::FONT_HERSHEY_TRIPLEX, + 1.0, cv::Scalar(0, 255, 0), 3); + + + + // imwrite(std::to_string(detection.object_id) + ".jpg", frame); + + Mat img = frame; + Mat tmp = img(detection.rect); + + + String imgName(std::to_string(detection.object_id) + ".jpg"); + String model_path(parser.get("model_path")); + String config_path(parser.get("config_path")); + + String path_label(parser.get("label_path")); + int width(parser.get("width")); + int height(parser.get("heigth")); + Scalar mean(parser.get("mean")); + int swapRB(parser.get("swap")); + + DnnClassificator dnn(model_path, config_path, + path_label, width, height, mean, swapRB); + + Mat image = tmp; + Mat prob; + //Image classification + + prob = dnn.Classify(image); + + //Show result + Point classIdPoint; + double confidence; + minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint); + + int classId = classIdPoint.x; + + if (classId >= 150 && classId <= 277 && confidence >= 0.6) { + + std::string name; + + std::ifstream in("../../CV-SUMMER-CAMP/data/squeezenet1.1.labels"); + int count = 0; + if (in.is_open()) + { + while (getline(in, name)) + { + if (count == classId) + { + break; + } + count++; + + } + } + in.close(); + + + + Mat res = image; + + putText(res, name, Point(30, 90), FONT_HERSHEY_COMPLEX_SMALL, 0.8, Scalar(200, 200, 250)); + + + imwrite("..//dogs//" + name + ".jpg", res); + } + + } + + imshow("Tracking by Matching", frame); + + char c = (char)waitKey(2); + if (c == 'q') + break; + if (c == 'p') + paused = !paused; + } + + double s = frame_counter / (time_total / getTickFrequency()); + printf("FPS: %f\n", s); + + return 0; +} diff --git a/src/classificator.cpp b/src/classificator.cpp index 2792f79..426d99a 100644 --- a/src/classificator.cpp +++ b/src/classificator.cpp @@ -1 +1,34 @@ -#include "classificator.h" \ No newline at end of file +#include "classificator.h" +#include + + + +DnnClassificator::DnnClassificator(string pthModel, string pthConfig, string pthLabels, int inputWidth, int inputHeight, Scalar myMean, int mySwapRB) +{ + model = pthModel; + config = pthConfig; + labels = pthLabels; + width = inputWidth; + height = inputHeight; + mean = myMean; + swapRB = mySwapRB; + + backendId = DNN_BACKEND_OPENCV; + targetId = DNN_TARGET_CPU; + net = readNet(model, config); + net.setPreferableBackend(backendId); + net.setPreferableTarget(targetId); + + scale = 1; + ddepth = CV_32F; + crop = false; +} + +Mat DnnClassificator::Classify(Mat image) +{ + Size spatialSize = Size(width, height); + blobFromImage(image, blob, scale, spatialSize, mean, swapRB, crop, ddepth); + net.setInput(blob); + + return net.forward(); +} diff --git a/src/filter.cpp b/src/filter.cpp index d2eaacd..76d8cb2 100644 --- a/src/filter.cpp +++ b/src/filter.cpp @@ -1 +1,26 @@ -#include "filter.h" \ No newline at end of file +#include "filter.h" + +Mat GrayFilter::ProcessImage(Mat image) +{ + Mat res(image.size(), CV_8UC1); + + // Filter image + + cvtColor(image, res, COLOR_RGB2GRAY); + + return res; +} + +ResizeFilter::ResizeFilter(int newWidth, int newHeight) +{ + width = newWidth; + height = newHeight; +} + +Mat ResizeFilter::ProcessImage(Mat image) +{ + Mat res; + resize(image, res, Size(width, height)); + return res; +} +