#include "FineMapping.h" namespace pr { const int FINEMAPPING_H = 60; const int FINEMAPPING_W = 140; const int PADDING_UP_DOWN = 30; void drawRect(cv::Mat image, cv::Rect rect) { cv::Point p1(rect.x, rect.y); cv::Point p2(rect.x + rect.width, rect.y + rect.height); cv::rectangle(image, p1, p2, cv::Scalar(0, 255, 0), 1); } FineMapping::FineMapping(std::string prototxt, std::string caffemodel) { net = cv::dnn::readNetFromCaffe(prototxt, caffemodel); } cv::Mat FineMapping::FineMappingHorizon(cv::Mat FinedVertical, int leftPadding, int rightPadding) { cv::Mat inputBlob = cv::dnn::blobFromImage( FinedVertical, 1 / 255.0, cv::Size(66, 16), cv::Scalar(0, 0, 0), false); net.setInput(inputBlob, "data"); cv::Mat prob = net.forward(); int front = static_cast(prob.at(0, 0) * FinedVertical.cols); int back = static_cast(prob.at(0, 1) * FinedVertical.cols); front -= leftPadding; if (front < 0) front = 0; back += rightPadding; if (back > FinedVertical.cols - 1) back = FinedVertical.cols - 1; cv::Mat cropped = FinedVertical.colRange(front, back).clone(); return cropped; } std::pair FitLineRansac(std::vector pts, int zeroadd = 0) { std::pair res; if (pts.size() > 2) { cv::Vec4f line; cv::fitLine(pts, line, cv::DIST_HUBER, 0, 0.01, 0.01); float vx = line[0]; float vy = line[1]; float x = line[2]; float y = line[3]; int lefty = static_cast((-x * vy / vx) + y); int righty = static_cast(((136 - x) * vy / vx) + y); res.first = lefty + PADDING_UP_DOWN + zeroadd; res.second = righty + PADDING_UP_DOWN + zeroadd; return res; } res.first = zeroadd; res.second = zeroadd; return res; } cv::Mat FineMapping::FineMappingVertical(cv::Mat InputProposal, int sliceNum, int upper, int lower, int windows_size) { cv::Mat PreInputProposal; cv::Mat proposal; cv::resize(InputProposal, PreInputProposal, cv::Size(FINEMAPPING_W, FINEMAPPING_H)); if (InputProposal.channels() == 3) cv::cvtColor(PreInputProposal, proposal, cv::COLOR_BGR2GRAY); else PreInputProposal.copyTo(proposal); // this will improve some sen cv::Mat kernal = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(1, 3)); float diff = static_cast(upper - lower); diff /= static_cast(sliceNum - 1); cv::Mat binary_adaptive; std::vector line_upper; std::vector line_lower; int contours_nums = 0; for (int i = 0; i < sliceNum; i++) { std::vector> contours; float k = lower + i * diff; cv::adaptiveThreshold(proposal, binary_adaptive, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, windows_size, k); cv::Mat draw; binary_adaptive.copyTo(draw); cv::findContours(binary_adaptive, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); for (auto contour : contours) { cv::Rect bdbox = cv::boundingRect(contour); float lwRatio = bdbox.height / static_cast(bdbox.width); int bdboxAera = bdbox.width * bdbox.height; if ((lwRatio > 0.7 && bdbox.width * bdbox.height > 100 && bdboxAera < 300) || (lwRatio > 3.0 && bdboxAera < 100 && bdboxAera > 10)) { cv::Point p1(bdbox.x, bdbox.y); cv::Point p2(bdbox.x + bdbox.width, bdbox.y + bdbox.height); line_upper.push_back(p1); line_lower.push_back(p2); contours_nums += 1; } } } if (contours_nums < 41) { cv::bitwise_not(InputProposal, InputProposal); cv::Mat kernal = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(1, 5)); cv::Mat bak; cv::resize(InputProposal, bak, cv::Size(FINEMAPPING_W, FINEMAPPING_H)); cv::erode(bak, bak, kernal); if (InputProposal.channels() == 3) cv::cvtColor(bak, proposal, cv::COLOR_BGR2GRAY); else proposal = bak; int contours_nums = 0; for (int i = 0; i < sliceNum; i++) { std::vector> contours; float k = lower + i * diff; cv::adaptiveThreshold(proposal, binary_adaptive, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, windows_size, k); cv::Mat draw; binary_adaptive.copyTo(draw); cv::findContours(binary_adaptive, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); for (auto contour : contours) { cv::Rect bdbox = cv::boundingRect(contour); float lwRatio = bdbox.height / static_cast(bdbox.width); int bdboxAera = bdbox.width * bdbox.height; if ((lwRatio > 0.7 && bdbox.width * bdbox.height > 120 && bdboxAera < 300) || (lwRatio > 3.0 && bdboxAera < 100 && bdboxAera > 10)) { cv::Point p1(bdbox.x, bdbox.y); cv::Point p2(bdbox.x + bdbox.width, bdbox.y + bdbox.height); line_upper.push_back(p1); line_lower.push_back(p2); contours_nums += 1; } } } } cv::Mat rgb; cv::copyMakeBorder(PreInputProposal, rgb, PADDING_UP_DOWN, PADDING_UP_DOWN, 0, 0, cv::BORDER_REPLICATE); std::pair A; std::pair B; A = FitLineRansac(line_upper, -1); B = FitLineRansac(line_lower, 1); int leftyB = A.first; int rightyB = A.second; int leftyA = B.first; int rightyA = B.second; int cols = rgb.cols; int rows = rgb.rows; std::vector corners(4); corners[0] = cv::Point2f(cols - 1, rightyA); corners[1] = cv::Point2f(0, leftyA); corners[2] = cv::Point2f(cols - 1, rightyB); corners[3] = cv::Point2f(0, leftyB); std::vector corners_trans(4); corners_trans[0] = cv::Point2f(136, 36); corners_trans[1] = cv::Point2f(0, 36); corners_trans[2] = cv::Point2f(136, 0); corners_trans[3] = cv::Point2f(0, 0); cv::Mat transform = cv::getPerspectiveTransform(corners, corners_trans); cv::Mat quad = cv::Mat::zeros(36, 136, CV_8UC3); cv::warpPerspective(rgb, quad, transform, quad.size()); return quad; } } // namespace pr