1. 程式人生 > >利用caffe搭建的深度學習demo

利用caffe搭建的深度學習demo

// This is a demo code for using a SSD model to do detection. // The code is modified from examples/cpp_classification/classification.cpp. // Usage: //    ssd_detect [FLAGS] model_file weights_file list_file // // where model_file is the .prototxt file defining the network architecture, and // weights_file is the .caffemodel file containing the network parameters, and // list_file contains a list of image files with the format as follows: //    folder/img1.JPEG //    folder/img2.JPEG // list_file can also contain a list of video files with the format as follows: //    folder/video1.mp4 //    folder/video2.mp4 // #include <caffe/caffe.hpp>

#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/opencv.hpp>

#include <algorithm> #include <iomanip> #include <iosfwd> #include <memory> #include <string> #include <utility> #include <vector> #include <fstream> #include <iostream>

#include "Time/calculateTime.h" #include <windows.h> #include <boost/algorithm/string.hpp> #include <string> #include <tchar.h> #include <fstream> #include <iostream> #include <string> #include <io.h> #include <vector> #include <direct.h>

//#define CPU_ONLY using namespace cv; using namespace caffe;  // NOLINT(build/namespaces)

void writelog(string msg) {     std::ofstream file("./log.txt", ios::out | ios::app);     file << msg << std::endl;     file.close(); }

class Detector { public:     Detector(const string& model_file, const string& weights_file, const string& mean_file, const string& mean_value);

    std::vector<vector<float> > Detect(const cv::Mat& img);

private:     void SetMean(const string& mean_file, const string& mean_value);

    void WrapInputLayer(std::vector<cv::Mat>* input_channels);

    void Preprocess(const cv::Mat& img, std::vector<cv::Mat>* input_channels);

private:     shared_ptr<Net<float> > net_;    //網路模型     cv::Size input_geometry_;    //輸入影象寬和高     int num_channels_;            //輸入影象通道數     cv::Mat mean_;                //均值影象 };

Detector::Detector(const string& model_file, const string& weights_file, const string& mean_file, const string& mean_value){ #ifdef CPU_ONLY     Caffe::set_mode(Caffe::CPU); #else     Caffe::set_mode(Caffe::GPU); #endif

    /* Load the network. */     net_.reset(new Net<float>(model_file, TEST));     net_->CopyTrainedLayersFrom(weights_file);

    CHECK_EQ(net_->num_inputs(), 1) << "Network should have exactly one input.";     CHECK_EQ(net_->num_outputs(), 1) << "Network should have exactly one output.";

    Blob<float>* input_layer = net_->input_blobs()[0];     num_channels_ = input_layer->channels();     CHECK(num_channels_ == 3 || num_channels_ == 1)         << "Input layer should have 1 or 3 channels.";     input_geometry_ = cv::Size(input_layer->width(), input_layer->height());

    /* Load the binaryproto mean file. */     SetMean(mean_file, mean_value); }

std::vector<vector<float> > Detector::Detect(const cv::Mat& img) {     Blob<float>* input_layer = net_->input_blobs()[0];     input_layer->Reshape(1, num_channels_, input_geometry_.height, input_geometry_.width);     /* Forward dimension change to all layers. */     net_->Reshape();

    std::vector<cv::Mat> input_channels;     WrapInputLayer(&input_channels);

    Preprocess(img, &input_channels);

    net_->Forward();

    /* Copy the output layer to a std::vector */     Blob<float>* result_blob = net_->output_blobs()[0];     const float* result = result_blob->cpu_data();     const int num_det = result_blob->height();     vector<vector<float> > detections;     for (int k = 0; k < num_det; ++k) {         if (result[0] == -1) {             // Skip invalid detection.             result += 7;             continue;         }         vector<float> detection(result, result + 7);         detections.push_back(detection);         result += 7;     }     return detections; }

/* Load the mean file in binaryproto format. */ void Detector::SetMean(const string& mean_file, const string& mean_value) {     cv::Scalar channel_mean;     if (!mean_file.empty()) {         CHECK(mean_value.empty()) <<             "Cannot specify mean_file and mean_value at the same time";         BlobProto blob_proto;         ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto);

        /* Convert from BlobProto to Blob<float> */         Blob<float> mean_blob;         mean_blob.FromProto(blob_proto);         CHECK_EQ(mean_blob.channels(), num_channels_)             << "Number of channels of mean file doesn't match input layer.";

        /* The format of the mean file is planar 32-bit float BGR or grayscale. */         std::vector<cv::Mat> channels;         float* data = mean_blob.mutable_cpu_data();         for (int i = 0; i < num_channels_; ++i) {             /* Extract an individual channel. */             cv::Mat channel(mean_blob.height(), mean_blob.width(), CV_32FC1, data);             channels.push_back(channel);             data += mean_blob.height() * mean_blob.width();         }

        /* Merge the separate channels into a single image. */         cv::Mat mean;         cv::merge(channels, mean);

        /* Compute the global mean pixel value and create a mean image         * filled with this value. */         channel_mean = cv::mean(mean);         mean_ = cv::Mat(input_geometry_, mean.type(), channel_mean);     }     if (!mean_value.empty()) {         CHECK(mean_file.empty()) <<             "Cannot specify mean_file and mean_value at the same time";         stringstream ss(mean_value);         vector<float> values;         string item;         while (getline(ss, item, ',')) {             float value = std::atof(item.c_str());             values.push_back(value);         }         CHECK(values.size() == 1 || values.size() == num_channels_) <<             "Specify either 1 mean_value or as many as channels: " << num_channels_;

        std::vector<cv::Mat> channels;         for (int i = 0; i < num_channels_; ++i) {             /* Extract an individual channel. */             cv::Mat channel(input_geometry_.height, input_geometry_.width, CV_32FC1,                 cv::Scalar(values[i]));             channels.push_back(channel);         }         cv::merge(channels, mean_);     } }

/* Wrap the input layer of the network in separate cv::Mat objects * (one per channel). This way we save one memcpy operation and we * don't need to rely on cudaMemcpy2D. The last preprocessing * operation will write the separate channels directly to the input * layer. */ void Detector::WrapInputLayer(std::vector<cv::Mat>* input_channels) {     Blob<float>* input_layer = net_->input_blobs()[0];

    int width = input_layer->width();     int height = input_layer->height();     float* input_data = input_layer->mutable_cpu_data();     for (int i = 0; i < input_layer->channels(); ++i) {         cv::Mat channel(height, width, CV_32FC1, input_data);         input_channels->push_back(channel);         input_data += width * height;     } }

void Detector::Preprocess(const cv::Mat& img, std::vector<cv::Mat>* input_channels) {     /* Convert the input image to the input image format of the network. */     cv::Mat sample;     if (img.channels() == 3 && num_channels_ == 1)         cv::cvtColor(img, sample, cv::COLOR_BGR2GRAY);     else if (img.channels() == 4 && num_channels_ == 1)         cv::cvtColor(img, sample, cv::COLOR_BGRA2GRAY);     else if (img.channels() == 4 && num_channels_ == 3)         cv::cvtColor(img, sample, cv::COLOR_BGRA2BGR);     else if (img.channels() == 1 && num_channels_ == 3)         cv::cvtColor(img, sample, cv::COLOR_GRAY2BGR);     else         sample = img;

    cv::Mat sample_resized;     if (sample.size() != input_geometry_)         cv::resize(sample, sample_resized, input_geometry_);     else         sample_resized = sample;

    cv::Mat sample_float;     if (num_channels_ == 3)         sample_resized.convertTo(sample_float, CV_32FC3);     else         sample_resized.convertTo(sample_float, CV_32FC1);

    cv::Mat sample_normalized;     cv::subtract(sample_float, mean_, sample_normalized);

    /* This operation will write the separate BGR planes directly to the     * input layer of the network because it is wrapped by the cv::Mat     * objects in input_channels. */     cv::split(sample_normalized, *input_channels);

    CHECK(reinterpret_cast<float*>(input_channels->at(0).data) == net_->input_blobs()[0]->cpu_data())         << "Input channels are not wrapping the input layer of the network."; }

DEFINE_string(mean_file, "",     "The mean file used to subtract from the input image."); DEFINE_string(mean_value, "104,117,123",     "If specified, can be one value or can be same as image channels"     " - would subtract from the corresponding channel). Separated by ','."     "Either mean_file or mean_value should be provided, not both."); DEFINE_string(file_type, "image",     "The file type in the list_file. Currently support image and video."); DEFINE_string(out_file, "",     "If provided, store the detection results in the out_file."); DEFINE_double(confidence_threshold, 0.01,     "Only store detections with score higher than the threshold.");

typedef struct RectInfo {     float x1;     float y1;     float x2;     float y2;     float score;     int label; } RectInfo;

bool CompareBBox(const RectInfo & a, const RectInfo & b) {     return a.score > b.score; }

std::vector<RectInfo> NonMaximumSuppression(std::vector<RectInfo>& bboxes,     float thresh, char methodType){     std::vector<RectInfo> bboxes_nms;     std::sort(bboxes.begin(), bboxes.end(), CompareBBox);

    int32_t select_idx = 0;     int32_t num_bbox = static_cast<int32_t>(bboxes.size());     std::vector<int32_t> mask_merged(num_bbox, 0);     bool all_merged = false;

    while (!all_merged) {         while (select_idx < num_bbox && mask_merged[select_idx] == 1)             select_idx++;         if (select_idx == num_bbox) {             all_merged = true;             continue;         }

        bboxes_nms.push_back(bboxes[select_idx]);         mask_merged[select_idx] = 1;

        RectInfo select_bbox = bboxes[select_idx];         float area1 = static_cast<float>((select_bbox.x2 - select_bbox.x1 + 1) * (select_bbox.y2 - select_bbox.y1 + 1));         float x1 = static_cast<float>(select_bbox.x1);         float y1 = static_cast<float>(select_bbox.y1);         float x2 = static_cast<float>(select_bbox.x2);         float y2 = static_cast<float>(select_bbox.y2);

        select_idx++;         for (int32_t i = select_idx; i < num_bbox; i++) {             if (mask_merged[i] == 1)                 continue;

            RectInfo& bbox_i = bboxes[i];             float x = std::max<float>(x1, static_cast<float>(bbox_i.x1));             float y = std::max<float>(y1, static_cast<float>(bbox_i.y1));             float w = std::min<float>(x2, static_cast<float>(bbox_i.x2)) - x + 1;             float h = std::min<float>(y2, static_cast<float>(bbox_i.y2)) - y + 1;             if (w <= 0 || h <= 0)                 continue;

            float area2 = static_cast<float>((bbox_i.x2 - bbox_i.x1 + 1) * (bbox_i.y2 - bbox_i.y1 + 1));             float area_intersect = w * h;

            switch (methodType) {             case 'u':                 if (static_cast<float>(area_intersect) / (area1 + area2 - area_intersect) > thresh)                     mask_merged[i] = 1;                 break;             case 'm':                 if (static_cast<float>(area_intersect) / min(area1, area2) > thresh)                     mask_merged[i] = 1;                 break;             default:                 break;             }         }     }     return bboxes_nms; }

bool LineFit(vector<int> arr_y, vector<int> arr_x, double& angle, double& a, double& b, double& c); Mat Rotatepara(Mat imgsrc); Mat rotateImage1(Mat img, double degree, int x, int y); Mat rotateImage1(Mat img, double degree, int x, int y) {     degree = -degree;     double angle = degree  * CV_PI / 180.;     double a = sin(angle), b = cos(angle);     int width = img.cols;     int height = img.rows;     int width_rotate = int(height * fabs(a) + width * fabs(b));     int height_rotate = int(width * fabs(a) + height * fabs(b));     float map[6];     Mat map_matrix = Mat(2, 3, CV_32F, map);     CvPoint2D32f center = cvPoint2D32f(y, x);     CvMat map_matrix2 = map_matrix;     cv2DRotationMatrix(center, degree, 1.0, &map_matrix2);     map[2] += (width_rotate - width) / 2;     map[5] += (height_rotate - height) / 2;     Mat img_rotate;     warpAffine(img, img_rotate, map_matrix, Size(width_rotate, height_rotate), 1, 0, 0);     return img_rotate; }

Mat  Rotatepara(Mat imgsrc) {     if (imgsrc.channels() == 3)     {         cvtColor(imgsrc, imgsrc, COLOR_RGB2GRAY);     }     Mat imgsrc_save = imgsrc.clone();     blur(imgsrc, imgsrc, Size(5, 5));     threshold(imgsrc, imgsrc, 15, 255, CV_THRESH_BINARY);     vector<vector<Point>> contours_con;     vector<Vec4i> hierarchy_con;     Mat  srcImg_con(imgsrc.size(), imgsrc.type(), Scalar::all(0));     findContours(imgsrc, contours_con, hierarchy_con, RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);     double area = 0;     int area_index = 0;     for (int i = 0; i < contours_con.size(); i++)     {

        if (area <= contourArea(contours_con[i]))         {             area = contourArea(contours_con[i]);             area_index = i;         }     }     drawContours(srcImg_con, contours_con, area_index, Scalar::all(255), -1);

    vector<int> arr_x;     vector<int> arr_y;     for (int i = imgsrc.rows / 6 + 1; i < imgsrc.rows; i = i + imgsrc.rows / 6 + 1)     {         const uchar* srcImg_con_data = srcImg_con.ptr<uchar>(i);         for (int j = 5; j < srcImg_con.cols - 5; j++)         {             if (abs(srcImg_con_data[j] - srcImg_con_data[j - 1]) == 255)             {                 arr_x.push_back(i);                 arr_y.push_back(j);                 break;             }         }     }     double  a, b, c, angle;     int x, y;     //y=-a/b*x-c/b     LineFit(arr_y, arr_x, angle, a, b, c);     x = imgsrc.rows / 2;     y = -a / (b + 0.000001)*x - c / (b + 0.000001);     double degree = angle * 180.0 / CV_PI;     Mat imgsrc_rotate = rotateImage1(srcImg_con, degree, x, y);     Mat imgsrc_save_rotate = rotateImage1(imgsrc_save, degree, x, y);

    //判斷側邊方向     const uchar* srcImg_con_data = srcImg_con.ptr<uchar>(srcImg_con.rows / 2);     int sum_left = 0, sum_right = 0;     for (int j = 0; j < srcImg_con.cols / 2; j++)     {         sum_left = sum_left + srcImg_con_data[j];         sum_right = sum_right + srcImg_con_data[srcImg_con.cols / 2 + j];     }

    vector<int> array_y;     if (sum_left>sum_right)     {         for (int i = imgsrc_rotate.rows / 6 + 1; i < imgsrc_rotate.rows; i = i + imgsrc_rotate.rows / 6 + 1)         {             const uchar* imgsrc_rotate_data = imgsrc_rotate.ptr<uchar>(i);             for (int j = 2; j < imgsrc_rotate.cols; j++)             {                 if (imgsrc_rotate_data[imgsrc_rotate.cols - j] == 255)                 {                     array_y.push_back(imgsrc_rotate.cols - j);                     break;                 }             }         }     }     else     {         for (int i = imgsrc_rotate.rows / 6 + 1; i < imgsrc_rotate.rows; i = i + imgsrc_rotate.rows / 6 + 1)         {             const uchar* imgsrc_rotate_data = imgsrc_rotate.ptr<uchar>(i);             for (int j = 2; j < imgsrc_rotate.cols; j++)             {                 if (imgsrc_rotate_data[j] == 255)                 {                     array_y.push_back(j);                     break;                 }             }         }     }

    //求平均橫座標     int sum = 0;     for (int i = 0; i < array_y.size(); i++)     {         sum = array_y[i] + sum;     }     int arerage_y = sum / (array_y.size() + 0.000001);

    Range Rcol;     if (sum_left>sum_right)     {         Rcol.start = arerage_y - 70 > 0 ? arerage_y - 70 : 0;         Rcol.end = arerage_y + 20 < imgsrc_rotate.cols ? arerage_y + 20 : imgsrc_rotate.cols;     }     else     {         Rcol.start = arerage_y - 20 > 0 ? arerage_y - 20 : 0;         Rcol.end = arerage_y + 70 < imgsrc_rotate.cols ? arerage_y + 70 : imgsrc_rotate.cols;     }

    Mat mask = Mat::Mat(imgsrc_save_rotate, Range::all(), Rcol);     return mask; } bool LineFit(vector<int> arr_y, vector<int> arr_x, double& angle, double& a, double& b, double& c) {     a = 0;     b = 0;     c = 0;     angle = 0;

    int size = (int)arr_y.size();     if (size < 2) return false;

    try     {         double x_mean = 0;         double y_mean = 0;         for (int i = 0; i < size; ++i)         {             x_mean += arr_x[i];             y_mean += arr_y[i];         }         x_mean /= size;         y_mean /= size; //至此,計算出了x y的均值

        double Dxx = 0, Dxy = 0, Dyy = 0;         for (int i = 0; i < size; ++i)         {             Dxx += (arr_x[i] - x_mean) * (arr_x[i] - x_mean);             Dxy += (arr_x[i] - x_mean) * (arr_y[i] - y_mean);             Dyy += (arr_y[i] - y_mean) * (arr_y[i] - y_mean);         }         double lambda = ((Dxx + Dyy) - sqrt((Dxx - Dyy) * (Dxx - Dyy) + 4 * Dxy * Dxy)) / 2.0;         double den = sqrt(Dxy * Dxy + (lambda - Dxx) * (lambda - Dxx));         if (den == 0) return false;

        a = Dxy / den;         b = (lambda - Dxx) / den;         c = -a * x_mean - b * y_mean;         if (b == 0)             angle = CV_PI / 2;         else             angle = atan(-a / b);

        return true;     }     catch (...)     {         a = 0;         b = 0;         c = 0;         angle = 0;         return false;     } }

void* MatToIplImage(Mat src) {     IplImage dst = src;   //將Mat類轉換成IplImage     return &dst;      //返回IplImage指標 } void getAllFiles(string path, vector<string>& files) {     long hFile = 0;     struct _finddata_t fileinfo;     string p;

    if ((hFile = _findfirst(p.assign(path).append("/*").c_str(), &fileinfo)) != -1)     {         while (_findnext(hFile, &fileinfo) == 0)             files.push_back(p.assign(path).append("/").append(fileinfo.name));         _findclose(hFile);     } }

Detector *detector1, *detector2; extern "C" __declspec(dllexport) void detect_init1(char *param[10]) {     const string& model_file = param[0];     const string& weights_file = param[1];     const string& mean_file = FLAGS_mean_file;     const string& mean_value = FLAGS_mean_value;     detector1 = new Detector(model_file, weights_file, mean_file, mean_value); } extern "C" __declspec(dllexport) void detect_init2(char *param[10]) {     const string& model_file = param[0];     const string& weights_file = param[1];     const string& mean_file = FLAGS_mean_file;     const string& mean_value = FLAGS_mean_value;     detector2 = new Detector(model_file, weights_file, mean_file, mean_value); } extern "C" __declspec(dllexport) void detect_dispose() {     delete detector1;     delete detector2; }

extern "C" __declspec(dllexport) int edge_detect(double param[10], double *result, unsigned char* src_img, unsigned char *dest_img1, unsigned char *dest_img2, unsigned char *dest_img_concat) {

    const  int width = param[0];     const  int height = param[1];     const  int resize_width = param[2];     const  int resize_height = param[3];     const double final_score = param[4];

    const float confidence_threshold = FLAGS_confidence_threshold;

    vector<string> labelNames = { "background", "defects" };     cv::Mat img;     cv::Mat imgsrc(height, width, CV_8UC3, src_img);     cv::imwrite("imgsrc.jpg", imgsrc);     double ratio_col = imgsrc.cols / 512.0;     double ratio_row = imgsrc.rows / 82.0;     resize(imgsrc, img, Size(512, 82));     cv::imwrite("img.jpg", img);     Mat merged(Size(512, 430), img.type(), Scalar::all(0));     vconcat(img, merged, img);     cv::imwrite("merged.jpg", merged);

    if (img.empty())     {         return -1;     }

    //檢測     std::vector<vector<float> > detections = detector1->Detect(img);

    vector<RectInfo> bboxes;

    for (int i = 0; i < detections.size(); ++i) {         const vector<float>& d = detections[i];         // Detection format: [image_id, label, score, xmin, ymin, xmax, ymax].         CHECK_EQ(d.size(), 7);         const float score = d[2];

        if (score >= 0.2) {             RectInfo tmpRect;             tmpRect.label = (int)d[1];             tmpRect.score = score;             tmpRect.x1 = d[3] * img.cols;             tmpRect.y1 = d[4] * img.rows;             tmpRect.x2 = d[5] * img.cols;             tmpRect.y2 = d[6] * img.rows;             bboxes.push_back(tmpRect);         }     }

    vector<RectInfo> boxSp1 = NonMaximumSuppression(bboxes, 0.2, 'u');     Mat img_con, img_con_left, img_con_right;     for (int i = 0; i < boxSp1.size(); i++)     {         int sc = boxSp1[i].score * 100;         string score_s = std::to_string(sc);         int xmin = boxSp1[i].x1;         int ymin = boxSp1[i].y1;         int xmax = boxSp1[i].x2;         int ymax = boxSp1[i].y2;         rectangle(img, cv::Point(xmin, ymin), cv::Point(xmax, ymax), cv::Scalar(0, 0, 255), 2);         putText(img, labelNames[boxSp1[i].label], cv::Point(xmin, ymin + 100), 1, 2, cv::Scalar(0, 0, 255), 2);         putText(img, score_s, cv::Point(xmin + 50, ymin + 50), 1, 1, cv::Scalar(255, 0, 0), 2);

        int xmin1 = xmin * ratio_col;         int ymin1 = ymin * ratio_row > 0 ? ymin * ratio_row : 0;         int xmax1 = xmax * ratio_col;         int ymax1 = ymax * ratio_row < imgsrc.rows - 1 ? ymax * ratio_row : imgsrc.rows - 1;

        Range Rrow;         Rrow.start = ymin1;         Rrow.end = ymax1;         Range Rcol;         Rcol.start = xmin1;         Rcol.end = xmax1;         Mat mask = Mat::Mat(imgsrc, Rrow, Rcol);

        //vector <string> fields;         //boost::split(fields, image_path, boost::is_any_of("."));         //string pic_name_temp = fields[0] + string("_") + std::to_string(i + 1) + "." + fields[1];         //cv::imwrite(string("../側邊截圖/") + pic_name_temp, mask);

        mask = Rotatepara(mask);         cvtColor(mask, mask, CV_GRAY2BGR);

        int ratio = sqrt(mask.rows / mask.cols) + 1;         int perrows = mask.rows / ratio;         vector<Mat> mutilmask;         for (int m = 0; m < ratio; m++)         {             Range R;             R.start = m*perrows;             R.end = (m + 1)*perrows;             mutilmask.push_back(Mat::Mat(mask, R, Range::all()));         }         Mat merged;         for (int k = 0; k < ratio - 1; k++)         {             if (k == 0)             {                 hconcat(mutilmask[k], mutilmask[k + 1], merged);             }             else             {                 hconcat(merged, mutilmask[k + 1], merged);             }         }         resize(merged, merged, Size(resize_width, resize_height));

        vector<string> labelNames2 = { "background", "defects" };

        img = merged;

        if (img.empty())         {             return -1;         }

        //檢測         std::vector<vector<float> > detections2 = detector2->Detect(img);

        bboxes.clear();         for (int i = 0; i < detections2.size(); ++i) {             const vector<float>& d = detections2[i];             // Detection format: [image_id, label, score, xmin, ymin, xmax, ymax].             CHECK_EQ(d.size(), 7);             const float score = d[2];

            if (score >= final_score) {                 RectInfo tmpRect;                 tmpRect.label = (int)d[1];                 tmpRect.score = score;                 tmpRect.x1 = d[3] * img.cols;                 tmpRect.y1 = d[4] * img.rows;                 tmpRect.x2 = d[5] * img.cols;                 tmpRect.y2 = d[6] * img.rows;                 bboxes.push_back(tmpRect);             }         }

        vector<RectInfo> boxSp = NonMaximumSuppression(bboxes, 0.2, 'u');

        for (int i = 0; i < boxSp.size(); i++)         {             int sc = boxSp[i].score * 100;             string score_s = std::to_string(sc);             int xmin = boxSp[i].x1;             int ymin = boxSp[i].y1;             int xmax = boxSp[i].x2;             int ymax = boxSp[i].y2;             rectangle(img, cv::Point(xmin, ymin), cv::Point(xmax, ymax), cv::Scalar(0, 0, 255), 2);             putText(img, labelNames[boxSp[i].label], cv::Point(xmin, ymin + 100), 1, 2, cv::Scalar(0, 0, 255), 2);             putText(img, score_s, cv::Point(xmin + 50, ymin + 50), 1, 1, cv::Scalar(255, 0, 0), 2);         }

        if ((boxSp1[i].x1 + boxSp1[i].x1) / 2 < 250){             memcpy(dest_img1, img.data, resize_width * resize_height * 3);             img.copyTo(img_con_left);         }         else {             memcpy(dest_img2, img.data, resize_width * resize_height * 3);             img.copyTo(img_con_right);         }

        bboxes.clear();     }     hconcat(img_con_left, img_con_right, img_con);     memcpy(dest_img_concat, img_con.data, 2 * resize_width * resize_height * 3);     return 0; }

extern "C" __declspec(dllexport) int nvcd_detect(double param[10], double *result, unsigned char* src_img, unsigned char *dest_img) {

    const  int width = param[0];     const  int height = param[1];     const  int resize_width = param[2];     const  int resize_height = param[3];     const double final_score = param[4];

    const float confidence_threshold = FLAGS_confidence_threshold;

    vector<string> labelNames = { "background", "defects" };     cv::Mat imgsrc(height, width, CV_8UC3, src_img);     if (imgsrc.channels() == 3)     {         cvtColor(imgsrc, imgsrc, COLOR_RGB2GRAY);     }     Mat imgsrc_save = imgsrc.clone();     blur(imgsrc, imgsrc, Size(5, 5));     threshold(imgsrc, imgsrc, 25, 255, CV_THRESH_BINARY);     vector<vector<Point>> contours_con;     vector<Vec4i> hierarchy_con;     Mat  srcImg_con(imgsrc.size(), imgsrc.type(), Scalar::all(0));     findContours(imgsrc, contours_con, hierarchy_con, RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);     double area = 0;     int area_index = 0;     for (int i = 0; i < contours_con.size(); i++)     {

        if (area <= contourArea(contours_con[i]))         {             area = contourArea(contours_con[i]);             area_index = i;         }     }     drawContours(srcImg_con, contours_con, area_index, Scalar::all(255), -1);     RotatedRect Box;     Box = minAreaRect(contours_con[area_index]);

    double rotation_angle = Box.angle;     if (rotation_angle < -45) rotation_angle = 90 + rotation_angle;     Mat M = getRotationMatrix2D(Box.center, rotation_angle, 1);     warpAffine(imgsrc_save, imgsrc_save, M, imgsrc_save.size());

    float angle, boxwidth, boxheight;     if (0 <= abs(Box.angle) && abs(Box.angle) <= 45){         boxwidth = Box.size.width;         boxheight = Box.size.height;     }     else if (45 < abs(Box.angle) && abs(Box.angle) <= 90){         boxwidth = Box.size.height;         boxheight = Box.size.width;     }

    Range Rcol;     Rcol.start = Box.center.x - boxwidth / 2;     Rcol.end = Box.center.x + boxwidth / 2;     Range Rrow;     Rrow.start = Box.center.y - boxheight / 2;     Rrow.end = Box.center.y + boxheight / 2;

    if (Rcol.start < 0) Rcol.start = 0;     if (Rrow.start < 0) Rrow.start = 0;     if (Rcol.end >imgsrc_save.cols) Rcol.end = imgsrc_save.cols;     if (Rrow.end >imgsrc_save.rows) Rrow.end = imgsrc_save.rows;

    Mat mask = Mat::Mat(imgsrc_save, Rrow, Rcol);

    cv::Mat img;     resize(mask, img, Size(resize_width, resize_height));     if (img.channels() == 1)     {         cvtColor(img, img, COLOR_GRAY2BGR);     }     if (img.empty())     {         return -1;     }

    //檢測     std::vector<vector<float> > detections = detector1->Detect(img);

    vector<RectInfo> bboxes;

    for (int i = 0; i < detections.size(); ++i) {         const vector<float>& d = detections[i];         // Detection format: [image_id, label, score, xmin, ymin, xmax, ymax].         CHECK_EQ(d.size(), 7);         const float score = d[2];

        if (score >= final_score) {             RectInfo tmpRect;             tmpRect.label = (int)d[1];             tmpRect.score = score;             tmpRect.x1 = d[3] * img.cols;             tmpRect.y1 = d[4] * img.rows;             tmpRect.x2 = d[5] * img.cols;             tmpRect.y2 = d[6] * img.rows;             bboxes.push_back(tmpRect);         }     }     vector<RectInfo> boxSp1 = NonMaximumSuppression(bboxes, 0.2, 'u');     double tmp_size = boxSp1.size();     *result = tmp_size;

    for (int i = 0; i < boxSp1.size(); i++)     {         int sc = boxSp1[i].score * 100;         string score_s = std::to_string(sc);         int xmin = boxSp1[i].x1;         int ymin = boxSp1[i].y1;         int xmax = boxSp1[i].x2;         int ymax = boxSp1[i].y2;         rectangle(img, cv::Point(xmin, ymin), cv::Point(xmax, ymax), cv::Scalar(0, 0, 255), 1);         //putText(img, labelNames[boxSp1[i].label], cv::Point(xmin, ymin + 100), 1, 2, cv::Scalar(0, 0, 255), 2);         putText(img, score_s, cv::Point(xmin + 20, ymin + 20), 1, 1, cv::Scalar(255, 0, 0), 2);

    }     bboxes.clear();     memcpy(dest_img, img.data, resize_width * resize_height * 3);     return 0; }

extern "C" __declspec(dllexport) int nvcd_crop(char* dir_path, int resize_width, int resize_height) {     vector<string> files;     getAllFiles(dir_path, files);     int pos = string(dir_path).find_last_of('\\');     string crop_path(string(dir_path).substr(0, pos) + "/nvcd_crop_images/");     if (access(crop_path.c_str(), 0) != 0) mkdir(crop_path.c_str());

    for (int i = 2; i < files.size(); i++)     {         Mat tmp_img = imread(files[i], 0);         Mat imgsrc_save;         tmp_img.copyTo(imgsrc_save);         blur(tmp_img, tmp_img, Size(5, 5));         threshold(tmp_img, tmp_img, 30, 255, CV_THRESH_BINARY);         vector<vector<Point>> contours_con;         vector<Vec4i> hierarchy_con;         findContours(tmp_img, contours_con, hierarchy_con, RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);         double area = 0;         int area_index = 0;         for (int i = 0; i < contours_con.size(); i++)         {

            if (area <= contourArea(contours_con[i]))             {                 area = contourArea(contours_con[i]);                 area_index = i;             }         }         RotatedRect Box;         Box = minAreaRect(contours_con[area_index]);

        double rotation_angle = Box.angle;         if (rotation_angle < -45) rotation_angle = 90 + rotation_angle;         Mat M = getRotationMatrix2D(Box.center, rotation_angle, 1);         warpAffine(imgsrc_save, imgsrc_save, M, imgsrc_save.size());

        float  boxwidth, boxheight;         if (0 <= abs(Box.angle) && abs(Box.angle) <= 45){             boxwidth = Box.size.width;             boxheight = Box.size.height;         }         else if (45 < abs(Box.angle) && abs(Box.angle) <= 90){             boxwidth = Box.size.height;             boxheight = Box.size.width;         }

        Range Rcol;         Rcol.start = Box.center.x - boxwidth / 2;         Rcol.end = Box.center.x + boxwidth / 2;         Range Rrow;         Rrow.start = Box.center.y - boxheight / 2;         Rrow.end = Box.center.y + boxheight / 2;         if (Rcol.start < 0) Rcol.start = 0;         if (Rrow.start < 0) Rrow.start = 0;         if (Rcol.end >imgsrc_save.cols) Rcol.end = imgsrc_save.cols;         if (Rrow.end >imgsrc_save.rows) Rrow.end = imgsrc_save.rows;

        Mat mask(imgsrc_save, Rrow, Rcol);

        cv::Mat img;         resize(mask, img, Size(resize_width, resize_height));         if (img.empty()) continue;         cvtColor(img, img, COLOR_GRAY2BGR);

        imwrite(crop_path + std::to_string(i - 1) + ".jpg", img);     }     return 0; }

extern "C" __declspec(dllexport) int edge_crop(char* dir_path, int resize_width, int resize_height) {

    vector<string> files;     getAllFiles(dir_path, files);     int pos = string(dir_path).find_last_of('\\');     string crop_path(string(dir_path).substr(0, pos) + "/側邊剪下圖/");     if (access(crop_path.c_str(), 0) != 0) mkdir(crop_path.c_str());

    for (int item = 2; item < files.size(); item++)     {         Mat imgsrc = imread(files[item], 0);         Mat img;         vector<string> labelNames = { "background", "defects" };         double ratio_col = imgsrc.cols / 512.0;         double ratio_row = imgsrc.rows / 82.0;         resize(imgsrc, img, Size(512, 82));         Mat merged(Size(512, 430), img.type(), Scalar::all(0));         vconcat(img, merged, img);

        if (img.empty())         {             continue;         }

        //檢測         std::vector<vector<float> > detections = detector1->Detect(img);

        vector<RectInfo> bboxes;

        for (int i = 0; i < detections.size(); ++i) {             const vector<float>& d = detections[i];             // Detection format: [image_id, label, score, xmin, ymin, xmax, ymax].             CHECK_EQ(d.size(), 7);             const float score = d[2];

            if (score >= 0.2) {                 RectInfo tmpRect;                 tmpRect.label = (int)d[1];                 tmpRect.score = score;                 tmpRect.x1 = d[3] * img.cols;                 tmpRect.y1 = d[4] * img.rows;                 tmpRect.x2 = d[5] * img.cols;                 tmpRect.y2 = d[6] * img.rows;                 bboxes.push_back(tmpRect);             }         }

        vector<RectInfo> boxSp1 = NonMaximumSuppression(bboxes, 0.2, 'u');         Mat img_con, img_con_left, img_con_right;         for (int i = 0; i < boxSp1.size(); i++)         {             int sc = boxSp1[i].score * 100;             string score_s = std::to_string(sc);             int xmin = boxSp1[i].x1;             int ymin = boxSp1[i].y1;             int xmax = boxSp1[i].x2;             int ymax = boxSp1[i].y2;

            int xmin1 = xmin * ratio_col;             int ymin1 = ymin * ratio_row > 0 ? ymin * ratio_row : 0;             int xmax1 = xmax * ratio_col;             int ymax1 = ymax * ratio_row < imgsrc.rows - 1 ? ymax * ratio_row : imgsrc.rows - 1;

            Range Rrow;             Rrow.start = ymin1;             Rrow.end = ymax1;             Range Rcol;             Rcol.start = xmin1;             Rcol.end = xmax1;             Mat mask = Mat::Mat(imgsrc, Rrow, Rcol);

            mask = Rotatepara(mask);

            int ratio = sqrt(mask.rows / mask.cols) + 1;             int perrows = mask.rows / ratio;             vector<Mat> mutilmask;             for (int m = 0; m < ratio; m++)             {                 Range R;                 R.start = m*perrows;                 R.end = (m + 1)*perrows;                 mutilmask.push_back(Mat::Mat(mask, R, Range::all()));             }             Mat merged_img;             for (int k = 0; k < ratio - 1; k++)             {                 if (k == 0)                 {                     hconcat(mutilmask[k], mutilmask[k + 1], merged_img);                 }                 else                 {                     hconcat(merged_img, mutilmask[k + 1], merged_img);                 }             }             resize(merged_img, merged_img, Size(resize_width, resize_height));

            cvtColor(merged_img, merged_img, COLOR_GRAY2BGR);

            imwrite(crop_path + std::to_string(item - 1) + "_" + std::to_string(i) + ".jpg", merged_img);         }     }     return 0; }