利用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; }