// // Created by UnknownObject on 2022/9/21. // Copyright (c) 2022 UnknownNetworkService. All rights reserved. // //交通灯识别 #include "traffic_light.h" namespace uns { //取三个数中的最大值 int TrafficLight::tri_max(int a, int b, int c) { return std::max(std::max(a, b), c); } //根据亮度获取亮起的灯的位置 cv::Mat TrafficLight::GetLight(const cv::Mat &img) { cv::Mat hsv; cv::cvtColor(img, hsv, cv::COLOR_BGR2HSV); cv::Mat chn_v(hsv.size(), CV_8UC1); for (int r = 0; r < hsv.rows; r++) { for (int c = 0; c < hsv.cols; c++) { uchar v = hsv.at(r, c)[2]; chn_v.at(r, c) = (v >= 250 ? 0 : 255); } } cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(11, 11)); cv::morphologyEx(chn_v, chn_v, cv::MORPH_CLOSE, kernel); cv::Rect max_validate_rect = GetMaxRect(chn_v); if (max_validate_rect.size().area() == 0) return cv::Mat(); return img(max_validate_rect); } //获取图片中面积最大的轮廓的外接矩形 cv::Rect TrafficLight::GetMaxRect(const cv::Mat &img) { cv::Rect max_rect; double max_rect_size = 0; std::vector hierarchy; std::vector> contours; cv::findContours(img, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE); //轮廓查找 for (auto &contour: contours) //检测所找到的轮廓 { double area = cv::contourArea(cv::Mat(contour)); if (area > (img.size().area() / 2.0)) continue; if (area > max_rect_size) { max_rect_size = area; max_rect = cv::boundingRect(contour); } } return max_rect; } //“远大于”函数 bool TrafficLight::MuchLarger(int a, int b, double rate) { return (a >= (b * rate)); } //识别灯的颜色 Light::TL_COLOR TrafficLight::GetImageColor(const cv::Mat &img, double rate) { int cnt_r = 0, cnt_g = 0, cnt_y = 0; int cnt_g_less = 0, cnt_b_less = 0; for (int r = 0; r < img.rows; r++) { for (int c = 0; c < img.cols; c++) { uns::Colors::CVColor color(img.at(r, c)); if (MuchLarger(color.GetR(), color.GetG(), rate) && MuchLarger(color.GetR(), color.GetB(), rate)) cnt_r++; else if (MuchLarger(color.GetG(), color.GetR(), rate) && MuchLarger(color.GetG(), color.GetB(), rate)) cnt_g++; else if (MuchLarger(color.GetB(), color.GetR(), rate) && MuchLarger(color.GetB(), color.GetG(), rate)) cnt_g++; else if (MuchLarger(color.GetR(), color.GetB(), rate) && MuchLarger(color.GetG(), color.GetB(), rate)) cnt_y++; if (color.GetG() < 110) cnt_g_less++; if (color.GetB() < 110) cnt_b_less++; } } LOGI("GLess: %d, BLess: %d", cnt_g_less, cnt_b_less); int cnt_max = tri_max(cnt_r, cnt_g, cnt_y); if ((cnt_max == cnt_r) || (cnt_max == cnt_y)) { if ((cnt_g_less < 50) /*&& (cnt_b_less < 5)*/) return Light::TL_COLOR::Yellow; else return Light::TL_COLOR::Red; } else if (cnt_max == cnt_g) return Light::TL_COLOR::Green; else return Light::TL_COLOR::Null; } //整合的识别函数 Light::TL_COLOR TrafficLight::Reco(cv::Mat &img) { LOGI("Begin Traffic Light"); img = GetLight(img); if (img.empty()) return Light::TL_COLOR::Null; LOGI("Traffic Light Finished"); cv::imwrite("/sdcard/MainCar/tlr_finished.jpg", img); return GetImageColor(img, 1.3); } }; //导出的识别函数 extern "C" JNIEXPORT jint JNICALL Java_com_uns_maincar_cpp_1interface_TrafficLight_Recognize(JNIEnv *env, jclass _this, jobject image) { cv::Mat img; if(!BitmapToMat(env,image,img)) return 4; cv::imwrite("/sdcard/MainCar/red.jpg", img); uns::TrafficLight traffic_light; switch(traffic_light.Reco(img)) { case uns::Light::TL_COLOR::Red: return 0; case uns::Light::TL_COLOR::Yellow: return 1; case uns::Light::TL_COLOR::Green: return 2; case uns::Light::TL_COLOR::Null: return 3; } return 5; } //导出的自检函数 extern "C" JNIEXPORT jstring JNICALL Java_com_uns_maincar_cpp_1interface_EnvTest_TrafficLightTest(JNIEnv *env, jclass _this) { std::string version = "TrafficLightReco Found, Version: " + std::string(TRAFFIC_LIGHT_RECO_VERSION); return env->NewStringUTF(version.c_str()); }