├── CMakeLists.txt ├── MobileYOLOv3 ├── README.md ├── dog-cycle-car.png ├── mobilenet.cpp ├── mobilenetv2_yolov3.bin └── mobilenetv2_yolov3.param /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(MobileYOLOv3) 3 | find_package(OpenCV REQUIRED) 4 | # find_package(ncnn REQUIRED) 5 | 6 | # set link library and head files of ncnn 7 | set(NCNN_LIBS "/home/northernjay/ncnn/build/install/lib/libncnn.a") 8 | set(NCNN_INCLUDE_DIRS "/home/northernjay/ncnn/build/install/include/ncnn") 9 | 10 | # configure OpenMP 11 | find_package(OpenMP REQUIRED) 12 | if(OPENMP_FOUND) 13 | message("OPENMP FOUND") 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 16 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 17 | endif() 18 | 19 | 20 | include_directories(${NCNN_INCLUDE_DIRS}) 21 | #include_directories(${OpenCV_INCLUDE_DIR}) 22 | #include_directories(${NCNN_INCLUDE_DIRSS}) 23 | 24 | get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) 25 | foreach(dir ${dirs}) 26 | message(STATUS "dir='${dir}'") 27 | endforeach() 28 | 29 | add_executable(MobileYOLOv3 mobilenet.cpp) 30 | target_link_libraries(MobileYOLOv3 ${OpenCV_LIBS} ${NCNN_LIBS}) 31 | -------------------------------------------------------------------------------- /MobileYOLOv3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/northernjay885/NCNN-Mobilenetv2-YOLOv3/06190f606817e7f82b9f5d6027a8f23afc591b00/MobileYOLOv3 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NCNN-Mobilenetv2-YOLOv3 2 | 3 | Build a YOLOv3 Convolutional Neural Network for object detection using NCNN framework. 4 | 5 | ## Getting Started 6 | 7 | ``` 8 | git clone https://github.com/northernjay885/NCNN-Mobilenetv2-YOLOv3.git 9 | ``` 10 | 11 | ### Prerequisites 12 | 13 | 14 | Install [CMake](https://cmake.org/download/). 15 | 16 | ### Installing 17 | 18 | Build OpenCV using CMake 19 | ``` 20 | cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local .. 21 | ``` 22 | ``` 23 | make -j8 # runs 8 jobs in parallel, depend on your CPU threads 24 | ``` 25 | Build NCNN framework following the [guide](https://github.com/Tencent/ncnn). 26 | 27 | ## Build objects 28 | 29 | in /build directory 30 | ``` 31 | cmake -D CMAKE_BUILD_TYPE=Release .. 32 | ``` 33 | 34 | ## Built With 35 | 36 | * [Cmake](https://cmake.org/) 37 | * [OpenCV](https://opencv.org/) 38 | * [NCNN](https://github.com/Tencent/ncnn) 39 | -------------------------------------------------------------------------------- /dog-cycle-car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/northernjay885/NCNN-Mobilenetv2-YOLOv3/06190f606817e7f82b9f5d6027a8f23afc591b00/dog-cycle-car.png -------------------------------------------------------------------------------- /mobilenet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "net.h" 10 | //#include "mat.h" 11 | #include "platform.h" 12 | 13 | struct Object 14 | { 15 | cv::Rect_ rect; 16 | int label; 17 | float prob; 18 | }; 19 | 20 | static int detect_yolov3(const cv::Mat& image, std::vector& objects) 21 | { 22 | const float probThreshold {0.5}; 23 | //load model and pretrained weights 24 | ncnn::Net net; 25 | net.load_param("mobilenetv2_yolov3.param"); 26 | net.load_model("mobilenetv2_yolov3.bin"); 27 | 28 | const int input_size = 352; 29 | 30 | int img_width = image.cols; 31 | int img_height = image.rows; 32 | 33 | ncnn::Mat ncnnImage = ncnn::Mat::from_pixels_resize(image.data, ncnn::Mat::PIXEL_BGR, img_width, img_height, input_size, input_size); 34 | 35 | //subtract range mean value, norm to (-1, 1) 36 | const float mean_vals[3] = {127.5f, 127.5f, 127.5f}; 37 | const float norm_vals[3] = {0.007843f, 0.007843f, 0.007843f}; 38 | ncnnImage.substract_mean_normalize(mean_vals, norm_vals); 39 | 40 | ncnn::Extractor ex = net.create_extractor(); 41 | ex.set_num_threads(4); 42 | 43 | ex.input("data", ncnnImage); 44 | 45 | ncnn::Mat detectRes; 46 | ex.extract("detection_out", detectRes); 47 | 48 | objects.clear(); 49 | 50 | for(int i = 0; i < detectRes.h; i++) 51 | { 52 | const float* values = detectRes.row(i); 53 | 54 | if(values[1] >= probThreshold) 55 | { 56 | Object object; 57 | object.label = values[0]; 58 | object.prob = values[1]; 59 | object.rect.x = values[2] * img_width; 60 | object.rect.y = values[3] * img_height; 61 | object.rect.width = values[4] * img_width - object.rect.x; 62 | object.rect.height = values[5] * img_height - object.rect.y; 63 | 64 | objects.push_back(object); 65 | } 66 | 67 | } 68 | 69 | return 0; 70 | 71 | } 72 | 73 | static void draw_objects(const cv::Mat& inputImage, const std::vector& objects) 74 | { 75 | static const char* class_name[] = {"background", 76 | "aeroplane", "bicycle", "bird", "boat", 77 | "bottle", "bus", "car", "cat", "chair", 78 | "cow", "diningtable", "dog", "horse", 79 | "motorbike", "person", "pottedplant", 80 | "sheep", "sofa", "train", "tvmonitor"}; 81 | 82 | cv::Mat image = inputImage.clone(); 83 | 84 | for(size_t i = 0; i < objects.size(); i++) 85 | { 86 | const Object& obj = objects[i]; 87 | cv::rectangle(image, obj.rect, cv::Scalar(50,205,50)); 88 | 89 | std::string text {""}; 90 | text += class_name[obj.label]; 91 | text += std::to_string(obj.prob * 100); 92 | text += "%"; 93 | 94 | int baseline = 0; 95 | cv::Size textSize = cv::getTextSize(text, cv::FONT_HERSHEY_DUPLEX, 0.5, 1, &baseline); 96 | 97 | int x = obj.rect.x; 98 | int y = obj.rect.y; 99 | if(y < 0) 100 | y = 0; 101 | if(x + textSize.width > image.cols) 102 | x = image.cols - textSize.width; 103 | 104 | //y + textSize.height for bottom left corner 105 | cv::rectangle(image, cv::Rect(x, y, textSize.width, textSize.height + 5), cv::Scalar(50,205,50), -1); 106 | cv::putText(image, text, cv::Point(x, y + textSize.height), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar(255,255,255)); 107 | } 108 | 109 | //cv::imshow("image", image); 110 | //cv::waitKey(0); 111 | } 112 | 113 | 114 | int main(int argc, char** argv) 115 | { 116 | cv::Mat frame; 117 | 118 | cv::VideoCapture cap; 119 | 120 | // 0 = open default camera 121 | int deviceID = 0; 122 | // 0 = autodetect default API 123 | int apiID = cv::CAP_ANY; 124 | 125 | //open camera 126 | cap.open(deviceID + apiID); 127 | 128 | if(!cap.isOpened()) 129 | { 130 | std::cerr<<"ERROR! Unable to open camera\n"; 131 | return -1; 132 | } 133 | 134 | //--- grab and write loop 135 | while(true) 136 | { 137 | cap.read(frame); 138 | if(frame.empty()) 139 | { 140 | std::cerr<<"ERROR! blank frame grabbed\n"; 141 | return -1; 142 | } 143 | 144 | std::vector objects; 145 | 146 | detect_yolov3(frame, objects); 147 | draw_objects(frame, objects); 148 | 149 | cv::imshow("image", frame); 150 | if(cv::waitKey(5) >= 0) 151 | break; 152 | } 153 | 154 | //cv::Mat image = cv::imread(imagepath, cv::IMREAD_COLOR); 155 | // if(image.empty()) 156 | // { 157 | // std::cerr<<"no image has been read!"<