You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
4.1 KiB
C++

//
// 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<cv::Vec3b>(r, c)[2];
chn_v.at<uchar>(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<cv::Vec4i> hierarchy;
std::vector<std::vector<cv::Point>> 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<cv::Vec3b>(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());
}