/** * Karaka * * @package Image * @copyright Dennis Eichhorn * @license OMS License 1.0 * @version 1.0.0 * @link https://karaka.app */ #ifndef IMAGE_BILL_DETECTION_H #define IMAGE_BILL_DETECTION_H #include #include #include namespace Image { class BillDetection { private: public: static cv::Mat highlightBill(cv::Mat in) { cv::Mat gray; cv::cvtColor(in, gray, cv::COLOR_BGR2GRAY); cv::GaussianBlur(gray, gray, cv::Size(3, 3), 0); cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Point(9, 9)); cv::Mat dilated; cv::dilate(gray, dilated, kernel); cv::Mat edges; cv::Canny(dilated, edges, 84, 3); std::vector lines; lines.clear(); cv::HoughLinesP(edges, lines, 1, CV_PI/180, 25); std::vector::iterator it = lines.begin(); for(; it != lines.end(); ++it) { cv::Vec4i l = *it; cv::line(edges, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255,0,0), 2, 8); } std::vector> contours; cv::findContours(edges, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_TC89_KCOS); std::vector> contoursCleaned; for (int i = 0; i < contours.size(); ++i) { if (cv::arcLength(contours[i], false) > 100) { contoursCleaned.push_back(contours[i]); } } std::vector> contoursArea; for (int i = 0; i < contoursCleaned.size(); ++i) { if (cv::contourArea(contoursCleaned[i]) > 10000) { contoursArea.push_back(contoursCleaned[i]); } } // Approximate polygon /* Question: we probably don't want a polygon all the time?! */ // @todo bad implementation, focus on single square std::vector > contoursDraw (contoursArea.size()); for (int i = 0; i < contoursArea.size(); ++i){ cv::approxPolyDP(cv::Mat(contoursArea[i]), contoursDraw[i], 40, true); } cv::Mat mask = cv::Mat(in.size(), CV_8UC3, cv::Scalar(255, 255, 255)); cv::drawContours(mask, contoursDraw, -1, cv::Scalar(0, 0, 0), cv::FILLED, 1); cv::Mat out = cv::Mat::zeros(in.size(), CV_8UC3); cv::bitwise_or(in, mask, out); return out; } }; } #endif