#include "detectionprocessing.h" #include "controller.h" #include #include #include #include #include #include #include #include using namespace std; using namespace cv; RateProcessing::RateProcessing(QObject* parent) : Processing(parent) {} void RateProcessing::init(Json::Value json_steps) { Processing::init(this->metaObject(), json_steps); } Mat RateProcessing::_dilate(const Mat& input, int kernel_size, int iterations) { Mat out; dilate(input, out, getStructuringElement(MORPH_ELLIPSE, Size(kernel_size, kernel_size)), Point(-1, -1), iterations); return out; } Mat RateProcessing::_threshold(const Mat& input, int ignored, int ignored2) { Mat gray; cvtColor(input, gray, COLOR_BGR2GRAY); Mat out; threshold(gray, out, 1, 255, THRESH_BINARY); return out; } Mat RateProcessing::_thresh_otsu(const Mat& input, int ignored, int ignored2) { Mat gray; cvtColor(input, gray, COLOR_BGR2GRAY); Mat out; threshold(gray, out, 0, 255, THRESH_BINARY | THRESH_OTSU); return out; } Mat RateProcessing::_invert(const Mat& input, int ignored, int ignored2) { Mat out = Scalar::all(255) - input; return out; } Mat RateProcessing::_thresh_color(const Mat& input, int lowerThreshold, int upperThreshold) { Mat hsv; cvtColor(input, hsv, COLOR_BGR2HSV); Mat out(input.size(), CV_8U); inRange(hsv, Scalar(lowerThreshold, 0, 0), Scalar(upperThreshold, 255, 255), out); return out; } Mat RateProcessing::_mean_color(const Mat& input, int ignored, int ignored2) { Mat hsv_nut; cvtColor(*getInput(), hsv_nut, CV_BGR2HSV); Scalar res = mean(hsv_nut, input); results["avg_h_val"] = res[0]; if (isInteractive()) { emit requestUpdate(); } return hsv_nut; } Mat RateProcessing::_erode(const Mat& input, int kernel_size, int iterations) { Mat out; erode(input, out, getStructuringElement(MORPH_ELLIPSE, Size(kernel_size, kernel_size)), Point(-1, -1), iterations); return out; } Mat RateProcessing::_hough(const Mat& input, int canny_1, int canny_2) { vector circles; Mat gray; cvtColor(input, gray, COLOR_BGR2GRAY); HoughCircles(gray, circles, HOUGH_GRADIENT, 1, input.rows/4, canny_1, canny_2); Mat out; input.copyTo(out); for (int i = 0; i> contours; Mat in; float fac = 1.0; if (input.rows > input.cols) { fac = (float) max_length/input.rows; } else { fac = (float) max_length/input.cols; } Size new_size((int)input.cols*fac, (int) input.rows*fac) ; resize(input, in, new_size); findContours(in, contours, RETR_LIST, CHAIN_APPROX_TC89_KCOS); Mat out; if (isInteractive()) { out = Mat::zeros(in.size(), CV_8UC3); for(int i = 0; i < contours.size(); i++) { drawContours(out, contours, i, Scalar::all(255), 1, 8); } } return out; } Mat RateProcessing::_find_contours(const Mat& input, int ignored, int ignored2) { Mat in = input.clone(); vector> contours; Mat out; findContours(in, contours, RETR_LIST, CHAIN_APPROX_NONE); if (isInteractive()) { out = Mat::zeros(input.size(), CV_8UC3); for(int i = 0; i < contours.size(); i++) { drawContours(out, contours, i, Scalar::all(255), 1, 8); } } return out; } Mat RateProcessing::_fit_ellipse(const Mat& input, int ignored, int ignored2) { Mat in = input.clone(); //vector> contours; contours = {}; Mat out; findContours(in, contours, RETR_LIST, CHAIN_APPROX_NONE); if (isInteractive()) { out = Mat::zeros(input.size(), CV_8UC3); } vector boxes = {}; for(int i = 0; i < contours.size(); i++) { int count = contours[i].size(); if( count < 6 ) continue; Mat pointsf; Mat(contours[i]).convertTo(pointsf, CV_32F); RotatedRect box = fitEllipse(pointsf); if( MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height)*30 ) continue; boxes.push_back(box); if (isInteractive()) { drawContours(out, contours, i, Scalar::all(255), 1, 8); ellipse(out, box, Scalar(0,0,255)); Point2f vtx[4]; box.points(vtx); for( int j = 0; j < 4; j++ ) { line(out, vtx[j], vtx[(j+1)%4], Scalar(0,255,0), 1, LINE_AA); } } } RotatedRect& max_box = boxes[0]; int max_area = 0; for (auto&& box : boxes) { if ((box.size.width * box.size.height) > max_area) { max_box = box; max_area = box.size.width * box.size.height; } } results["size_ratio"] = max_box.size.width/max_box.size.height; results["size_diagonal"] = sqrt(max_box.size.height * max_box.size.height + max_box.size.height * max_box.size.height) / static_cast(steps[current_step].getParam1()); if (isInteractive()) { emit requestUpdate(); } return out; } Mat RateProcessing::_rate_spots(const Mat& input, int ignored, int ignored2) { Mat in = input.clone(); vector> contours; Mat out; findContours(in, contours, RETR_LIST, CHAIN_APPROX_NONE); if (isInteractive()) { out = Mat::zeros(input.size(), CV_8UC3); } vector boxes = {}; // image and mask of spots vector> spots = {}; for(int i = 0; i < contours.size(); i++) { int count = contours[i].size(); if( count < 6 ) continue; Mat pointsf; Mat(contours[i]).convertTo(pointsf, CV_32F); RotatedRect box = fitEllipse(pointsf); if( MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height)*30 ) continue; boxes.push_back(box); if (isInteractive()) { drawContours(out, contours, i, Scalar::all(255), 1, 8); ellipse(out, box, Scalar(0,0,255)); Point2f vtx[4]; box.points(vtx); for( int j = 0; j < 4; j++ ) { line(out, vtx[j], vtx[(j+1)%4], Scalar(0,255,0), 1, LINE_AA); } } // extract spot from image Rect roi = boundingRect(contours[i]); Mat mask = Mat::zeros(input.size(), CV_8UC1); drawContours(mask, contours, i, Scalar(255), CV_FILLED); Mat contourRegion; Mat imageROI; getInput()->copyTo(imageROI, mask); contourRegion = imageROI(roi); Mat maskRegion = mask(roi); spots.push_back(make_tuple(contourRegion, maskRegion)); } // find largest ellipse to ignore it, because its no spot but the nut itself int max_box_index = -1; int max_area = 0; for (unsigned int i = 0; i max_area) { max_box_index = i; max_area = boxes[i].size.width * boxes[i].size.height; } } double box_avg_size = 0.0f; for (unsigned int i = 0; i 1) { box_avg_size /= static_cast(boxes.size() - 1); } else { box_avg_size = 0.0f; } results["spot_avg_size"] = box_avg_size/steps[current_step].getParam1(); double spot_avg_h_val = 0.0f; for (unsigned int i = 0; i(spots[i]), hsv_spot, CV_BGR2HSV); Scalar res = mean(hsv_spot, get<1>(spots[i])); spot_avg_h_val += res[0]; } if (spots.size() > 1) { spot_avg_h_val /= static_cast(spots.size() - 1); } else { spot_avg_h_val = 0.0f; } results["spot_avg_h_val"] = spot_avg_h_val; if (isInteractive()) { emit requestUpdate(); } return out; } void RateProcessing::reset() { current_step = 0; InputType type = steps[0].getInputType(); if (type == color) { steps[0].setInput(Controller::inst().getCurNut()); } results.clear(); rateCurNut = true; } map RateProcessing::getResults() { return results; } const cv::Mat* RateProcessing::getInput() { if (rateCurNut) { return Controller::inst().getCurNut(); } else { return Controller::inst().getNutToRate(); } } const vector>& RateProcessing::getContours() { return contours; } void RateProcessing::setRateCurNut(bool val) { rateCurNut = val; }