add colored qr code
This commit is contained in:
@@ -165,6 +165,21 @@ add_library( # Sets the name of the library.
|
||||
lib_hyper_lpr/src/SegmentationFreeRecognizer.cpp
|
||||
lib_hyper_lpr/javaWarpper.cpp)
|
||||
|
||||
add_library( # Sets the name of the library.
|
||||
colored_qr_code
|
||||
|
||||
# Sets the library as a shared library.
|
||||
SHARED
|
||||
|
||||
# Provides a relative path to your source file(s).
|
||||
color_reco.cpp
|
||||
public_types.cpp
|
||||
opencv_support.cpp
|
||||
opencv_libqr/cv_qrcode.cpp
|
||||
colored_qr_detect/QRCode.cpp
|
||||
colored_qr_detect/QRCodeSet.cpp
|
||||
colored_qr_detect/colored_qr_decode.cpp)
|
||||
|
||||
# Searches for a specified prebuilt library and stores the path as a
|
||||
# variable. Because CMake includes system libraries in the search path by
|
||||
# default, you only need to specify the name of the public NDK library
|
||||
@@ -287,3 +302,12 @@ target_link_libraries( # Specifies the target library.
|
||||
${OpenCV_LIBS}
|
||||
${jnigraphics-lib}
|
||||
${log-lib})
|
||||
|
||||
target_link_libraries( # Specifies the target library.
|
||||
colored_qr_code
|
||||
|
||||
# Links the target library to the log library
|
||||
# included in the NDK.
|
||||
${OpenCV_LIBS}
|
||||
${jnigraphics-lib}
|
||||
${log-lib})
|
||||
|
||||
@@ -16,13 +16,13 @@ namespace uns
|
||||
}
|
||||
|
||||
//识别颜色,逐像素便利并统计出现次数最多的颜色作为最终结果
|
||||
std::string ColorReco::RecoColor(const cv::Mat& img)
|
||||
Colors::CVColor ColorReco::RecoColor(const cv::Mat &img)
|
||||
{
|
||||
int max_count = 0;
|
||||
std::string color_name = "null";
|
||||
Colors::CVColor max_color;
|
||||
Colors::ColorCount counter = basic_color_counter;
|
||||
if (img.empty())
|
||||
return color_name;
|
||||
return std_color_white;
|
||||
for (int r = 0; r < img.rows; r++)
|
||||
{
|
||||
for (int c = 0; c < img.cols; c++)
|
||||
@@ -46,17 +46,42 @@ namespace uns
|
||||
counter[std_color_white]++;
|
||||
}
|
||||
}
|
||||
for (auto& ele : counter)
|
||||
for (auto &ele: counter)
|
||||
{
|
||||
if ((ele.first == std_color_white)/* || (ele.first == std_color_yellow)*/)
|
||||
if ((ele.first == std_color_white))
|
||||
continue;
|
||||
if (ele.second > max_count)
|
||||
{
|
||||
max_color = ele.first;
|
||||
max_count = ele.second;
|
||||
color_name = color_name_map.at(ele.first);
|
||||
}
|
||||
}
|
||||
return color_name;
|
||||
return max_color;
|
||||
}
|
||||
|
||||
std::string ColorReco::RecoColorStr(const Colors::CVColor &color)
|
||||
{
|
||||
return color_name_map.at(color);
|
||||
}
|
||||
|
||||
bool ColorReco::IsRed(const Colors::CVColor &result)
|
||||
{
|
||||
return (result == std_color_red);
|
||||
}
|
||||
|
||||
bool ColorReco::IsGreen(const Colors::CVColor &result)
|
||||
{
|
||||
return (result == std_color_green);
|
||||
}
|
||||
|
||||
bool ColorReco::IsBlue(const Colors::CVColor &result)
|
||||
{
|
||||
return (result == std_color_blue);
|
||||
}
|
||||
|
||||
bool ColorReco::IsYellow(const Colors::CVColor &result)
|
||||
{
|
||||
return (result == std_color_yellow);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -44,19 +44,31 @@ namespace uns
|
||||
};
|
||||
std::map<Colors::CVColor, std::string> color_name_map =
|
||||
{
|
||||
{ std_color_red, "red" },
|
||||
{ std_color_green, "green"},
|
||||
{ std_color_blue, "blue"},
|
||||
{ std_color_yellow, "yellow"},
|
||||
{ std_color_purple, "purple"},
|
||||
{ std_color_cyan, "cyan"},
|
||||
{ std_color_black, "black"},
|
||||
{ std_color_white, "white"},
|
||||
{std_color_red, "red" },
|
||||
{std_color_green, "green"},
|
||||
{std_color_blue, "blue"},
|
||||
{std_color_yellow, "yellow"},
|
||||
{std_color_purple, "purple"},
|
||||
{std_color_cyan, "cyan"},
|
||||
{std_color_black, "black"},
|
||||
{std_color_white, "white"},
|
||||
};
|
||||
private:
|
||||
bool MuchLarger(int a, int b, double rate);
|
||||
|
||||
public:
|
||||
std::string RecoColor(const cv::Mat& img);
|
||||
Colors::CVColor RecoColor(const cv::Mat &img);
|
||||
|
||||
std::string RecoColorStr(const Colors::CVColor &color);
|
||||
|
||||
public:
|
||||
bool IsRed(const Colors::CVColor &result);
|
||||
|
||||
bool IsGreen(const Colors::CVColor &result);
|
||||
|
||||
bool IsBlue(const Colors::CVColor &result);
|
||||
|
||||
bool IsYellow(const Colors::CVColor &result);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "QRCode.h"
|
||||
|
||||
namespace uns
|
||||
{
|
||||
bool QRCode::IsSameRect(const cv::Rect &r1, const cv::Rect &r2) const
|
||||
{
|
||||
cv::Point c1 = r1.tl();
|
||||
cv::Point c2 = r2.tl();
|
||||
int x_offset = __ABS__(c1.x - c2.x);
|
||||
int y_offset = __ABS__(c1.y - c2.y);
|
||||
return ((x_offset <= EQUAL_OFFSET) && (y_offset <= EQUAL_OFFSET));
|
||||
}
|
||||
|
||||
QRCode::QRCode()
|
||||
{
|
||||
color = Color::Invalidate;
|
||||
}
|
||||
|
||||
QRCode::QRCode(const cv::Rect &r)
|
||||
{
|
||||
position = r;
|
||||
color = Color::Invalidate;
|
||||
}
|
||||
|
||||
QRCode::QRCode(const QRCode &obj)
|
||||
{
|
||||
color = obj.color;
|
||||
position = obj.position;
|
||||
}
|
||||
|
||||
QRCode::QRCode(Color c, const cv::Rect &r)
|
||||
{
|
||||
color = c;
|
||||
position = r;
|
||||
}
|
||||
|
||||
QRCode::Color QRCode::GetColor() const
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
cv::Rect QRCode::GetRect() const
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
void QRCode::SetColor(Color color)
|
||||
{
|
||||
this->color = color;
|
||||
}
|
||||
|
||||
void QRCode::SetRect(const cv::Rect &rect)
|
||||
{
|
||||
position = rect;
|
||||
}
|
||||
|
||||
bool QRCode::operator==(const QRCode &obj) const
|
||||
{
|
||||
return IsSameRect(position, obj.position);
|
||||
}
|
||||
|
||||
bool QRCode::operator!=(const QRCode &obj) const
|
||||
{
|
||||
return (!IsSameRect(position, obj.position));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <opencv2/core/core.hpp>
|
||||
|
||||
#define __ABS__(x) (x < 0 ? -x : x)
|
||||
|
||||
namespace uns
|
||||
{
|
||||
class QRCode
|
||||
{
|
||||
public:
|
||||
enum class Color
|
||||
{
|
||||
Red = 0,
|
||||
Green = 1,
|
||||
Yellow = 2,
|
||||
Blue = 3,
|
||||
Invalidate = -1
|
||||
};
|
||||
private:
|
||||
Color color;
|
||||
cv::Rect position;
|
||||
const int EQUAL_OFFSET = 2;
|
||||
private:
|
||||
bool IsSameRect(const cv::Rect &r1, const cv::Rect &r2) const;
|
||||
|
||||
public:
|
||||
QRCode();
|
||||
|
||||
QRCode(const cv::Rect &r);
|
||||
|
||||
QRCode(const QRCode &obj);
|
||||
|
||||
QRCode(Color c, const cv::Rect &r);
|
||||
|
||||
public:
|
||||
Color GetColor() const;
|
||||
|
||||
cv::Rect GetRect() const;
|
||||
|
||||
void SetColor(Color color);
|
||||
|
||||
void SetRect(const cv::Rect &rect);
|
||||
|
||||
public:
|
||||
bool operator==(const QRCode &obj) const;
|
||||
|
||||
bool operator!=(const QRCode &obj) const;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "QRCodeSet.h"
|
||||
|
||||
namespace uns
|
||||
{
|
||||
QRCodeSet::QRCodeSet()
|
||||
{
|
||||
}
|
||||
|
||||
QRCodeSet::QRCodeSet(const QRCodeSet &obj)
|
||||
{
|
||||
qr_codes.clear();
|
||||
qr_codes.shrink_to_fit();
|
||||
current_index = obj.current_index;
|
||||
for (auto &ele: obj.qr_codes)
|
||||
qr_codes.push_back(ele);
|
||||
}
|
||||
|
||||
void QRCodeSet::Clear()
|
||||
{
|
||||
qr_codes.clear();
|
||||
current_index = 0;
|
||||
}
|
||||
|
||||
size_t QRCodeSet::Size()
|
||||
{
|
||||
return qr_codes.size();
|
||||
}
|
||||
|
||||
bool QRCodeSet::HasNextCode()
|
||||
{
|
||||
return (current_index < qr_codes.size());
|
||||
}
|
||||
|
||||
void QRCodeSet::ResetPointer()
|
||||
{
|
||||
current_index = 0;
|
||||
}
|
||||
|
||||
QRCode &QRCodeSet::GetNextCode()
|
||||
{
|
||||
return qr_codes[current_index++];
|
||||
}
|
||||
|
||||
void QRCodeSet::Insert(const QRCode &obj, const cv::Mat &source_img)
|
||||
{
|
||||
for (auto &ele: qr_codes)
|
||||
if (ele == obj)
|
||||
return;
|
||||
if (obj.GetColor() != QRCode::Color::Invalidate)
|
||||
qr_codes.push_back(obj);
|
||||
else
|
||||
{
|
||||
QRCode code(obj);
|
||||
ColorReco color_reco;
|
||||
Colors::CVColor result = color_reco.RecoColor(source_img(code.GetRect()));
|
||||
if (color_reco.IsRed(result))
|
||||
code.SetColor(QRCode::Color::Red);
|
||||
else if (color_reco.IsGreen(result))
|
||||
code.SetColor(QRCode::Color::Green);
|
||||
else if (color_reco.IsBlue(result))
|
||||
code.SetColor(QRCode::Color::Blue);
|
||||
else if (color_reco.IsYellow(result))
|
||||
code.SetColor(QRCode::Color::Yellow);
|
||||
qr_codes.push_back(code);
|
||||
}
|
||||
}
|
||||
|
||||
QRCode &QRCodeSet::operator[](size_t index)
|
||||
{
|
||||
return qr_codes[index];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "QRCode.h"
|
||||
#include "../color_reco.h"
|
||||
|
||||
namespace uns
|
||||
{
|
||||
class QRCodeSet
|
||||
{
|
||||
private:
|
||||
int current_index = 0;
|
||||
std::vector<QRCode> qr_codes;
|
||||
public:
|
||||
QRCodeSet();
|
||||
|
||||
QRCodeSet(const QRCodeSet &obj);
|
||||
|
||||
public:
|
||||
void Clear();
|
||||
|
||||
size_t Size();
|
||||
|
||||
bool HasNextCode();
|
||||
|
||||
void ResetPointer();
|
||||
|
||||
QRCode &GetNextCode();
|
||||
|
||||
void Insert(const QRCode &obj, const cv::Mat &source_img);
|
||||
|
||||
public:
|
||||
QRCode &operator[](size_t index);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
#include "colored_qr_decode.h"
|
||||
|
||||
namespace uns
|
||||
{
|
||||
SingleQRImage::SingleQRImage()
|
||||
{
|
||||
color = QRCode::Color::Invalidate;
|
||||
}
|
||||
|
||||
SingleQRImage::SingleQRImage(const SingleQRImage &img)
|
||||
{
|
||||
color = img.color;
|
||||
img.binary.copyTo(binary);
|
||||
img.colored.copyTo(colored);
|
||||
}
|
||||
|
||||
SingleQRImage::SingleQRImage(const cv::Mat &clr_src, const RGBChannel &rgb_src,
|
||||
const QRCode &code)
|
||||
{
|
||||
clr_src(code.GetRect()).copyTo(colored);
|
||||
switch (code.GetColor())
|
||||
{
|
||||
case QRCode::Color::Red:
|
||||
rgb_src[1](code.GetRect()).copyTo(binary);
|
||||
break;
|
||||
case QRCode::Color::Green:
|
||||
rgb_src[0](code.GetRect()).copyTo(binary);
|
||||
break;
|
||||
case QRCode::Color::Blue:
|
||||
rgb_src[0](code.GetRect()).copyTo(binary);
|
||||
break;
|
||||
case QRCode::Color::Yellow:
|
||||
rgb_src[2](code.GetRect()).copyTo(binary);
|
||||
break;
|
||||
default:
|
||||
clr_src(code.GetRect()).copyTo(binary);
|
||||
break;
|
||||
}
|
||||
color = code.GetColor();
|
||||
}
|
||||
|
||||
bool SingleQRImage::DataValidate() const
|
||||
{
|
||||
return ((!binary.empty()) && (!colored.empty()));
|
||||
}
|
||||
|
||||
QRCode::Color SingleQRImage::GetColor() const
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
cv::Mat SingleQRImage::GetBinaryImage() const
|
||||
{
|
||||
return binary;
|
||||
}
|
||||
|
||||
cv::Mat SingleQRImage::GetColoredImage() const
|
||||
{
|
||||
return colored;
|
||||
}
|
||||
|
||||
RGBChannel ColoredQrDecode::SplitRGBChannel(const cv::Mat &obj)
|
||||
{
|
||||
cv::Mat r(obj.size(), CV_8UC1), g(obj.size(), CV_8UC1), b(obj.size(), CV_8UC1);
|
||||
for (int i = 0; i < obj.rows; i++)
|
||||
{
|
||||
for (int j = 0; j < obj.cols; j++)
|
||||
{
|
||||
cv::Vec3b pixel = obj.at<cv::Vec3b>(i, j);
|
||||
r.at<uchar>(i, j) = pixel[2];
|
||||
g.at<uchar>(i, j) = pixel[1];
|
||||
b.at<uchar>(i, j) = pixel[0];
|
||||
}
|
||||
}
|
||||
return RGBChannel({r, g, b});
|
||||
}
|
||||
|
||||
//旋转图片45°
|
||||
bool ColoredQrDecode::RotateImage(const cv::Mat &src, cv::Mat &dst, float angle)
|
||||
{
|
||||
if (src.empty())
|
||||
return false;
|
||||
double alpha = -angle * CV_PI / 180.0;//convert angle to radian format
|
||||
cv::Point2f srcP[3];
|
||||
cv::Point2f dstP[3];
|
||||
srcP[0] = cv::Point2f(0, (float) src.rows);
|
||||
srcP[1] = cv::Point2f((float) src.cols, 0);
|
||||
srcP[2] = cv::Point2f((float) src.cols, (float) src.rows);
|
||||
//rotate the pixels
|
||||
for (int i = 0; i < 3; i++)
|
||||
dstP[i] = cv::Point2f(srcP[i].x * cos(alpha) - srcP[i].y * sin(alpha),
|
||||
srcP[i].y * cos(alpha) + srcP[i].x * sin(alpha));
|
||||
double minx, miny, maxx, maxy;
|
||||
minx = std::min(std::min(std::min(dstP[0].x, dstP[1].x), dstP[2].x), float(0.0));
|
||||
miny = std::min(std::min(std::min(dstP[0].y, dstP[1].y), dstP[2].y), float(0.0));
|
||||
maxx = std::max(std::max(std::max(dstP[0].x, dstP[1].x), dstP[2].x), float(0.0));
|
||||
maxy = std::max(std::max(std::max(dstP[0].y, dstP[1].y), dstP[2].y), float(0.0));
|
||||
int w = maxx - minx;
|
||||
int h = maxy - miny;
|
||||
//translation
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (minx < 0)
|
||||
dstP[i].x -= minx;
|
||||
if (miny < 0)
|
||||
dstP[i].y -= miny;
|
||||
}
|
||||
cv::Mat warpMat = cv::getAffineTransform(srcP, dstP);
|
||||
cv::warpAffine(src, dst, warpMat, cv::Size(w, h), 1, 0,
|
||||
cv::Scalar(255, 255, 255));//extend size
|
||||
return true;
|
||||
}
|
||||
|
||||
//使用导出的OpenCV库切分多个二维码
|
||||
bool ColoredQrDecode::SplitMultipleQR(const cv::Mat &img, std::vector<cv::Rect> &rects)
|
||||
{
|
||||
uns_cv_export::QRCodeDetector qrcode;
|
||||
std::vector<cv::Point> corners;
|
||||
if (!qrcode.detectMulti(img, corners))
|
||||
return false;
|
||||
if (!corners.empty())
|
||||
{
|
||||
if ((corners.size() % 4) != 0)
|
||||
return false;
|
||||
for (size_t i = 0; i < corners.size(); i += 4)
|
||||
rects.push_back(cv::boundingRect(
|
||||
std::vector<cv::Point>(corners.begin() + i, corners.begin() + i + 4)));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//检查是否有下一个二维码图片
|
||||
bool ColoredQrDecode::HasNextImage()
|
||||
{
|
||||
return qr_codes.HasNextCode();
|
||||
}
|
||||
|
||||
//获取下一个二维码图片
|
||||
SingleQRImage ColoredQrDecode::GetNextImage()
|
||||
{
|
||||
return SingleQRImage(source_image, split_channel_image, qr_codes.GetNextCode());
|
||||
}
|
||||
|
||||
//获取指定颜色的二维码
|
||||
SingleQRImage ColoredQrDecode::GetCodeByColor(QRCode::Color color)
|
||||
{
|
||||
qr_codes.ResetPointer();
|
||||
while (qr_codes.HasNextCode())
|
||||
{
|
||||
QRCode code = qr_codes.GetNextCode();
|
||||
if (code.GetColor() == color)
|
||||
{
|
||||
qr_codes.ResetPointer();
|
||||
return SingleQRImage(source_image, split_channel_image, code);
|
||||
}
|
||||
}
|
||||
qr_codes.ResetPointer();
|
||||
return SingleQRImage();
|
||||
}
|
||||
|
||||
//切分并存储二维码
|
||||
bool ColoredQrDecode::SplitQR(const cv::Mat &img, bool rotate_45)
|
||||
{
|
||||
std::vector<cv::Rect> rects;
|
||||
if (rotate_45)
|
||||
RotateImage(img, source_image, 45.00f);
|
||||
else
|
||||
img.copyTo(source_image);
|
||||
qr_codes.Clear();
|
||||
split_channel_image = SplitRGBChannel(source_image);
|
||||
SplitMultipleQR(split_channel_image[0], rects);
|
||||
SplitMultipleQR(split_channel_image[1], rects);
|
||||
SplitMultipleQR(split_channel_image[2], rects);
|
||||
for (const auto &ele: rects)
|
||||
qr_codes.Insert(QRCode(ele), source_image);
|
||||
return (qr_codes.Size() != 0);
|
||||
}
|
||||
|
||||
//清空存储
|
||||
void ColoredQrDecode::Clear()
|
||||
{
|
||||
qr_codes.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
uns::ColoredQrDecode global_colored_qr_decoder;
|
||||
uns::QRCode::Color global_current_qr_color = uns::QRCode::Color::Invalidate;
|
||||
|
||||
//导出的图像处理函数
|
||||
extern "C" JNIEXPORT
|
||||
jboolean JNICALL
|
||||
Java_com_uns_maincar_cpp_1interface_ColoredQRDecoder_ProcessColoredQR(JNIEnv *env, jclass _this,
|
||||
jobject image,
|
||||
jboolean rotate)
|
||||
{
|
||||
cv::Mat img_input;
|
||||
if (!BitmapToMat(env, image, img_input))
|
||||
return false;
|
||||
global_colored_qr_decoder.Clear();
|
||||
return global_colored_qr_decoder.SplitQR(img_input, rotate);
|
||||
}
|
||||
|
||||
//导出的检查是否有下一个二维码函数
|
||||
extern "C" JNIEXPORT
|
||||
jboolean JNICALL
|
||||
Java_com_uns_maincar_cpp_1interface_ColoredQRDecoder_HasNextQR(JNIEnv *env, jclass _this)
|
||||
{
|
||||
return global_colored_qr_decoder.HasNextImage();
|
||||
}
|
||||
|
||||
//导出的获取下一个二维码图片函数
|
||||
extern "C" JNIEXPORT
|
||||
jobject JNICALL
|
||||
Java_com_uns_maincar_cpp_1interface_ColoredQRDecoder_GetNextQR(JNIEnv *env, jclass _this)
|
||||
{
|
||||
uns::SingleQRImage qr_img = global_colored_qr_decoder.GetNextImage();
|
||||
global_current_qr_color = qr_img.GetColor();
|
||||
cv::Mat next = qr_img.GetBinaryImage();
|
||||
jobject bmp = GenerateBitmap(env, next.cols, next.rows);
|
||||
MatToBitmap(env, next, bmp);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
//导出的获取当前返回的二维码颜色函数
|
||||
extern "C" JNIEXPORT
|
||||
jint JNICALL
|
||||
Java_com_uns_maincar_cpp_1interface_ColoredQRDecoder_GetCurrentQRColor(JNIEnv *env, jclass _this)
|
||||
{
|
||||
return (jint) global_current_qr_color;
|
||||
}
|
||||
|
||||
//导出的根据指定颜色获取二维码函数
|
||||
extern "C" JNIEXPORT
|
||||
jobject JNICALL
|
||||
Java_com_uns_maincar_cpp_1interface_ColoredQRDecoder_GetSpecColorQR(JNIEnv *env, jclass _this,
|
||||
jint color)
|
||||
{
|
||||
cv::Mat next = global_colored_qr_decoder.GetCodeByColor(
|
||||
(uns::QRCode::Color) color).GetBinaryImage();
|
||||
jobject bmp = GenerateBitmap(env, next.cols, next.rows);
|
||||
MatToBitmap(env, next, bmp);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
//导出的强制清空函数
|
||||
extern "C" JNIEXPORT
|
||||
void JNICALL
|
||||
Java_com_uns_maincar_cpp_1interface_ColoredQRDecoder_ForceClear(JNIEnv *env, jclass _this)
|
||||
{
|
||||
global_colored_qr_decoder.Clear();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include <array>
|
||||
#include <jni.h>
|
||||
#include <vector>
|
||||
#include "QRCodeSet.h"
|
||||
#include "../opencv_support.h"
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include "../opencv_libqr/cv_qrcode.h"
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
|
||||
namespace uns
|
||||
{
|
||||
using RGBChannel = std::array<cv::Mat, 3>;
|
||||
|
||||
class SingleQRImage
|
||||
{
|
||||
private:
|
||||
cv::Mat binary;
|
||||
cv::Mat colored;
|
||||
QRCode::Color color;
|
||||
public:
|
||||
SingleQRImage();
|
||||
|
||||
SingleQRImage(const SingleQRImage &img);
|
||||
|
||||
SingleQRImage(const cv::Mat &clr_src, const RGBChannel &rgb_src, const QRCode &code);
|
||||
|
||||
public:
|
||||
bool DataValidate() const;
|
||||
|
||||
QRCode::Color GetColor() const;
|
||||
|
||||
cv::Mat GetBinaryImage() const;
|
||||
|
||||
cv::Mat GetColoredImage() const;
|
||||
};
|
||||
|
||||
class ColoredQrDecode
|
||||
{
|
||||
private:
|
||||
QRCodeSet qr_codes;
|
||||
cv::Mat source_image;
|
||||
RGBChannel split_channel_image;
|
||||
private:
|
||||
RGBChannel SplitRGBChannel(const cv::Mat &obj);
|
||||
|
||||
bool RotateImage(const cv::Mat &src, cv::Mat &dst, float angle);
|
||||
|
||||
bool SplitMultipleQR(const cv::Mat &img, std::vector<cv::Rect> &rects);
|
||||
|
||||
public:
|
||||
void Clear();
|
||||
|
||||
bool HasNextImage();
|
||||
|
||||
SingleQRImage GetNextImage();
|
||||
|
||||
SingleQRImage GetCodeByColor(QRCode::Color color);
|
||||
|
||||
bool SplitQR(const cv::Mat &img, bool rotate_45 = false);
|
||||
};
|
||||
};
|
||||
@@ -61,6 +61,17 @@ public class Commands
|
||||
public static byte OCR_TEXT_DATA = (byte) 0xD9;
|
||||
public static byte OCR_TEXT_FINISH = (byte) 0xE9;
|
||||
|
||||
//车型
|
||||
public static byte VEHICLE_SUCCESS = (byte) 0xAA;
|
||||
public static byte VEHICLE_FAILURE = (byte) 0xBA;
|
||||
public static byte VEHICLE_TYPE_BIKE = (byte) 0x0A;
|
||||
public static byte VEHICLE_TYPE_MOTOR = (byte) 0x0B;
|
||||
public static byte VEHICLE_TYPE_CAR = (byte) 0x0C;
|
||||
public static byte VEHICLE_TYPE_TRUCK = (byte) 0x0D;
|
||||
public static byte VEHICLE_TYPE_VAN = (byte) 0x0E;
|
||||
public static byte VEHICLE_TYPE_BUS = (byte) 0x0F;
|
||||
|
||||
|
||||
//运行指定任务
|
||||
public static byte RUN_SINGE_TASK = (byte) 0xA0;
|
||||
public static byte TASK_NUMBER_0 = 0x00;
|
||||
@@ -98,4 +109,5 @@ public class Commands
|
||||
public static final byte RECEIVE_TRAFFIC_SIGN = (byte) 0xA6;
|
||||
public static final byte RECEIVE_TEXT_OCR = (byte) 0xA7;
|
||||
public static final byte RECEIVE_OCR_DATA_OK = (byte) 0xB7;
|
||||
public static final byte RECEIVE_VEHICLE = (byte) 0xA8;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2023. UnknownNetworkService Group
|
||||
* This file is created by UnknownObject at 2023 - 6 - 16
|
||||
*/
|
||||
|
||||
package com.uns.maincar.cpp_interface;
|
||||
|
||||
import static com.uns.maincar.cpp_interface.QRDecoder.ERR_DECODE_FAILED;
|
||||
import static com.uns.maincar.cpp_interface.QRDecoder.ERR_IMAGE_GENERATOR_FAILED;
|
||||
import static com.uns.maincar.cpp_interface.QRDecoder.ERR_NATIVE_LIBRARY_FAILED;
|
||||
import static com.uns.maincar.cpp_interface.QRDecoder.ERR_NO_CODE_DETECTED;
|
||||
import static com.uns.maincar.cpp_interface.QRDecoder.ERR_NO_MORE_CODE;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import com.uns.maincar.constants.GlobalColor;
|
||||
import com.zxingcpp.BarcodeReader;
|
||||
|
||||
public class ColoredQRDecoder
|
||||
{
|
||||
static
|
||||
{
|
||||
System.loadLibrary("colored_qr_code");
|
||||
}
|
||||
|
||||
public static final String ERR_COLOR_INVALIDATE = "QR: Invalid Color Parameter.";
|
||||
|
||||
private static native void ForceClear();
|
||||
|
||||
private static native Bitmap GetNextQR();
|
||||
|
||||
private static native boolean HasNextQR();
|
||||
|
||||
private static native int GetCurrentQRColor();
|
||||
|
||||
private static native Bitmap GetSpecColorQR(int color);
|
||||
|
||||
private static native boolean ProcessColoredQR(Bitmap image, boolean rotate);
|
||||
|
||||
public static boolean BeginQRDecode(Bitmap img, boolean rotate)
|
||||
{
|
||||
return ProcessColoredQR(img, rotate);
|
||||
}
|
||||
|
||||
public static boolean HasNextCode()
|
||||
{
|
||||
return HasNextQR();
|
||||
}
|
||||
|
||||
public static String DecodeNextQR()
|
||||
{
|
||||
BarcodeReader reader = new BarcodeReader();
|
||||
if (HasNextQR())
|
||||
{
|
||||
Bitmap bmp = GetNextQR();
|
||||
if (bmp == null)
|
||||
return ERR_IMAGE_GENERATOR_FAILED;
|
||||
BarcodeReader.Result result = reader.read(bmp, QRDecoder.GetRect(bmp), 0);
|
||||
if (result != null)
|
||||
return result.getText();
|
||||
else
|
||||
return ERR_DECODE_FAILED;
|
||||
}
|
||||
else
|
||||
return ERR_NO_MORE_CODE;
|
||||
}
|
||||
|
||||
public static GlobalColor GetThisQRColor()
|
||||
{
|
||||
switch (GetCurrentQRColor())
|
||||
{
|
||||
case 0:
|
||||
return GlobalColor.RED;
|
||||
case 1:
|
||||
return GlobalColor.GREEN;
|
||||
case 2:
|
||||
return GlobalColor.YELLOW;
|
||||
case 3:
|
||||
return GlobalColor.BLUE;
|
||||
}
|
||||
return GlobalColor.INVALIDATE;
|
||||
}
|
||||
|
||||
public static String DecodeSpecColorQR(GlobalColor color)
|
||||
{
|
||||
int i_color = -1;
|
||||
switch (color)
|
||||
{
|
||||
case RED:
|
||||
i_color = 0;
|
||||
break;
|
||||
case GREEN:
|
||||
i_color = 1;
|
||||
break;
|
||||
case YELLOW:
|
||||
i_color = 2;
|
||||
break;
|
||||
case BLUE:
|
||||
i_color = 3;
|
||||
break;
|
||||
}
|
||||
if (i_color <= -1)
|
||||
return ERR_COLOR_INVALIDATE;
|
||||
BarcodeReader reader = new BarcodeReader();
|
||||
Bitmap bmp = GetSpecColorQR(i_color);
|
||||
if (bmp == null)
|
||||
return ERR_IMAGE_GENERATOR_FAILED;
|
||||
BarcodeReader.Result result = reader.read(bmp, QRDecoder.GetRect(bmp), 0);
|
||||
if (result != null)
|
||||
return result.getText();
|
||||
else
|
||||
return ERR_DECODE_FAILED;
|
||||
}
|
||||
|
||||
public static String SelfTest(Bitmap img)
|
||||
{
|
||||
if (!ProcessColoredQR(img, false))
|
||||
return ERR_NATIVE_LIBRARY_FAILED;
|
||||
if (!HasNextQR())
|
||||
return ERR_NO_CODE_DETECTED;
|
||||
String result = DecodeNextQR();
|
||||
ForceClear();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,9 @@ public class QRDecoder
|
||||
private static native Bitmap GetNextQR();
|
||||
private static native boolean ProcessQR(Bitmap image);
|
||||
|
||||
private static Rect GetRect(Bitmap img)
|
||||
protected static Rect GetRect(Bitmap img)
|
||||
{
|
||||
return new Rect(0,0,img.getWidth(),img.getHeight());
|
||||
return new Rect(0, 0, img.getWidth(), img.getHeight());
|
||||
}
|
||||
|
||||
public static boolean BeginQRDecode(Bitmap img)
|
||||
|
||||
@@ -15,6 +15,8 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.uns.maincar.R;
|
||||
import com.uns.maincar.constants.Flags;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class DebugPage extends AppCompatActivity
|
||||
{
|
||||
|
||||
@@ -27,6 +29,8 @@ public class DebugPage extends AppCompatActivity
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_debug_page);
|
||||
|
||||
Objects.requireNonNull(getSupportActionBar()).setTitle("主车远端服务程序 - 调试");
|
||||
|
||||
if (Parent == null)
|
||||
{
|
||||
Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show();
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
package com.uns.maincar.gui;
|
||||
|
||||
import static com.uns.maincar.cpp_interface.ColoredQRDecoder.ERR_COLOR_INVALIDATE;
|
||||
import static com.uns.maincar.cpp_interface.QRDecoder.ERR_DECODE_FAILED;
|
||||
import static com.uns.maincar.cpp_interface.QRDecoder.ERR_IMAGE_GENERATOR_FAILED;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
@@ -36,15 +40,14 @@ import com.uns.maincar.communication.WifiTransferCore;
|
||||
import com.uns.maincar.constants.Commands;
|
||||
import com.uns.maincar.constants.Flags;
|
||||
import com.uns.maincar.constants.Flags.TrafficLightColors;
|
||||
import com.uns.maincar.constants.GlobalSignType;
|
||||
import com.uns.maincar.constants.GlobalColor;
|
||||
import com.uns.maincar.cpp_interface.CarLicense;
|
||||
import com.uns.maincar.cpp_interface.ColoredQRDecoder;
|
||||
import com.uns.maincar.cpp_interface.EnvTest;
|
||||
import com.uns.maincar.cpp_interface.MainCarAES;
|
||||
import com.uns.maincar.cpp_interface.OCR;
|
||||
import com.uns.maincar.cpp_interface.QRDecoder;
|
||||
import com.uns.maincar.cpp_interface.ShapeColor;
|
||||
import com.uns.maincar.cpp_interface.TrafficLight;
|
||||
import com.uns.maincar.cpp_interface.TrafficSign;
|
||||
import com.uns.maincar.data_type.ShapeColorResult;
|
||||
import com.uns.maincar.open_source.shape.ShapeDetector;
|
||||
import com.uns.maincar.open_source.traffic_sign.YoloV5_tfLite_TSDetector;
|
||||
@@ -173,7 +176,8 @@ public class MainActivity extends AppCompatActivity
|
||||
break;
|
||||
//收到QR指令,开始识别二维码,回传识别成功的数据
|
||||
case Commands.RECEIVE_QR:
|
||||
byte[] cmd = RecognizeQrCode();
|
||||
//默认情况下使用黑白二维码识别
|
||||
byte[] cmd = RecognizeQrCode(false, GlobalColor.INVALIDATE);
|
||||
if (cmd[2] == Commands.QR_FAILED)
|
||||
dtc_client.Send(cmd);
|
||||
else
|
||||
@@ -204,7 +208,9 @@ public class MainActivity extends AppCompatActivity
|
||||
case Commands.RECEIVE_TEXT_OCR:
|
||||
OCRRecognizeText();
|
||||
break;
|
||||
//收到未知指令,回传异常指令,表示无法解析当前指令
|
||||
case Commands.RECEIVE_VEHICLE:
|
||||
dtc_client.Send(RecognizeVehicle());
|
||||
//收到未知指令,回传异常指令,表示无法解析当前指令
|
||||
default:
|
||||
CommandEncoder error = new CommandEncoder();
|
||||
dtc_client.Send(error.GenerateCommand(Commands.CMD_NOT_MATCH, (byte) 0x00, (byte) 0x00, (byte) 0x00));
|
||||
@@ -249,6 +255,16 @@ public class MainActivity extends AppCompatActivity
|
||||
return MainCarAES.CalcAES(validate_result);
|
||||
}
|
||||
|
||||
//处理彩色二维码数据,使用从C++代码中导出的算法
|
||||
private byte[] ProcessColoredQRData(String qr_data)
|
||||
{
|
||||
CommandEncoder encoder = new CommandEncoder();
|
||||
if (qr_data.equals(""))
|
||||
return encoder.GenerateCommand(Commands.QR_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||
else
|
||||
return MainCarAES.CalcAES(qr_data);
|
||||
}
|
||||
|
||||
//获取程序自检指令,根据自检状态返回成功或失败
|
||||
private byte[] SystemStatusCommand()
|
||||
{
|
||||
@@ -260,20 +276,39 @@ public class MainActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
//识别二维码
|
||||
private byte[] RecognizeQrCode()
|
||||
private byte[] RecognizeQrCode(boolean colored, GlobalColor target_color)
|
||||
{
|
||||
CommandEncoder encoder = new CommandEncoder();
|
||||
ArrayList<String> qr_result = new ArrayList<>();
|
||||
if (!QRDecoder.BeginQRDecode(currImage))
|
||||
return encoder.GenerateCommand(Commands.QR_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||
while (QRDecoder.HasNextCode())
|
||||
qr_result.add(QRDecoder.DecodeNextQR());
|
||||
if (qr_result.size() <= 0)
|
||||
return encoder.GenerateCommand(Commands.QR_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||
if (!colored)
|
||||
{
|
||||
ArrayList<String> qr_result = new ArrayList<>();
|
||||
if (!QRDecoder.BeginQRDecode(currImage))
|
||||
return encoder.GenerateCommand(Commands.QR_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||
while (QRDecoder.HasNextCode())
|
||||
qr_result.add(QRDecoder.DecodeNextQR());
|
||||
if (qr_result.size() <= 0)
|
||||
return encoder.GenerateCommand(Commands.QR_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||
else
|
||||
{
|
||||
qr_result.forEach(qr -> ToastLog(qr, false, true));
|
||||
return ProcessQRData(qr_result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qr_result.forEach(qr -> ToastLog(qr, false, true));
|
||||
return ProcessQRData(qr_result);
|
||||
boolean success = ColoredQRDecoder.BeginQRDecode(currImage, false);
|
||||
if (!success)
|
||||
success = ColoredQRDecoder.BeginQRDecode(currImage, true);
|
||||
if (!success)
|
||||
return encoder.GenerateCommand(Commands.QR_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||
String result = ColoredQRDecoder.DecodeSpecColorQR(target_color);
|
||||
if (Objects.equals(result, ERR_COLOR_INVALIDATE) || Objects.equals(result, ERR_IMAGE_GENERATOR_FAILED) || Objects.equals(result, ERR_DECODE_FAILED))
|
||||
return encoder.GenerateCommand(Commands.QR_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||
else
|
||||
{
|
||||
ToastLog(target_color + ":" + result, false, true);
|
||||
return ProcessColoredQRData(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,54 +335,20 @@ public class MainActivity extends AppCompatActivity
|
||||
private byte[] RecognizeShapeColor()
|
||||
{
|
||||
CommandEncoder encoder = new CommandEncoder();
|
||||
if (!ShapeColor.RecognizeEverything(currImage))
|
||||
/*if (!ShapeColor.RecognizeEverything(currImage))
|
||||
return encoder.GenerateCommand(Commands.COLOR_SHAPE_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||
else
|
||||
{
|
||||
byte a = 0, b = 0, c = 0;
|
||||
//测试用输出
|
||||
/*ToastLog("C-R-"+ShapeColor.LookupResult(GlobalShape.CIRCLE, GlobalColor.RED), false, false);
|
||||
ToastLog("C-BL-"+ShapeColor.LookupResult(GlobalShape.CIRCLE, GlobalColor.BLACK), false, false);
|
||||
ToastLog("C-G-"+ShapeColor.LookupResult(GlobalShape.CIRCLE, GlobalColor.GREEN), false, false);
|
||||
ToastLog("C-BU-"+ShapeColor.LookupResult(GlobalShape.CIRCLE, GlobalColor.BLUE), false, false);
|
||||
ToastLog("C-C-"+ShapeColor.LookupResult(GlobalShape.CIRCLE, GlobalColor.CYAN), false, false);
|
||||
ToastLog("C-P-"+ShapeColor.LookupResult(GlobalShape.CIRCLE, GlobalColor.PURPLE), false, false);
|
||||
ToastLog("C-W-"+ShapeColor.LookupResult(GlobalShape.CIRCLE, GlobalColor.WHITE), false, false);
|
||||
ToastLog("C-Y-"+ShapeColor.LookupResult(GlobalShape.CIRCLE, GlobalColor.YELLOW), false, false);
|
||||
ToastLog("S-R-"+ShapeColor.LookupResult(GlobalShape.STAR, GlobalColor.RED), false, false);
|
||||
ToastLog("S-BL-"+ShapeColor.LookupResult(GlobalShape.STAR, GlobalColor.BLACK), false, false);
|
||||
ToastLog("S-G-"+ShapeColor.LookupResult(GlobalShape.STAR, GlobalColor.GREEN), false, false);
|
||||
ToastLog("S-BU-"+ShapeColor.LookupResult(GlobalShape.STAR, GlobalColor.BLUE), false, false);
|
||||
ToastLog("S-C-"+ShapeColor.LookupResult(GlobalShape.STAR, GlobalColor.CYAN), false, false);
|
||||
ToastLog("S-P-"+ShapeColor.LookupResult(GlobalShape.STAR, GlobalColor.PURPLE), false, false);
|
||||
ToastLog("S-W-"+ShapeColor.LookupResult(GlobalShape.STAR, GlobalColor.WHITE), false, false);
|
||||
ToastLog("S-Y-"+ShapeColor.LookupResult(GlobalShape.STAR, GlobalColor.YELLOW), false, false);
|
||||
ToastLog("s-R-"+ShapeColor.LookupResult(GlobalShape.SQUARE, GlobalColor.RED), false, false);
|
||||
ToastLog("s-BL-"+ShapeColor.LookupResult(GlobalShape.SQUARE, GlobalColor.BLACK), false, false);
|
||||
ToastLog("s-G-"+ShapeColor.LookupResult(GlobalShape.SQUARE, GlobalColor.GREEN), false, false);
|
||||
ToastLog("s-BU-"+ShapeColor.LookupResult(GlobalShape.SQUARE, GlobalColor.BLUE), false, false);
|
||||
ToastLog("s-C-"+ShapeColor.LookupResult(GlobalShape.SQUARE, GlobalColor.CYAN), false, false);
|
||||
ToastLog("s-P-"+ShapeColor.LookupResult(GlobalShape.SQUARE, GlobalColor.PURPLE), false, false);
|
||||
ToastLog("s-W-"+ShapeColor.LookupResult(GlobalShape.SQUARE, GlobalColor.WHITE), false, false);
|
||||
ToastLog("s-Y-"+ShapeColor.LookupResult(GlobalShape.SQUARE, GlobalColor.YELLOW), false, false);
|
||||
ToastLog("R-R-"+ShapeColor.LookupResult(GlobalShape.RECTANGLE, GlobalColor.RED), false, false);
|
||||
ToastLog("R-BL-"+ShapeColor.LookupResult(GlobalShape.RECTANGLE, GlobalColor.BLACK), false, false);
|
||||
ToastLog("R-G-"+ShapeColor.LookupResult(GlobalShape.RECTANGLE, GlobalColor.GREEN), false, false);
|
||||
ToastLog("R-BU-"+ShapeColor.LookupResult(GlobalShape.RECTANGLE, GlobalColor.BLUE), false, false);
|
||||
ToastLog("R-C-"+ShapeColor.LookupResult(GlobalShape.RECTANGLE, GlobalColor.CYAN), false, false);
|
||||
ToastLog("R-P-"+ShapeColor.LookupResult(GlobalShape.RECTANGLE, GlobalColor.PURPLE), false, false);
|
||||
ToastLog("R-W-"+ShapeColor.LookupResult(GlobalShape.RECTANGLE, GlobalColor.WHITE), false, false);
|
||||
ToastLog("R-Y-"+ShapeColor.LookupResult(GlobalShape.RECTANGLE, GlobalColor.YELLOW), false, false);
|
||||
ToastLog("T-R-"+ShapeColor.LookupResult(GlobalShape.TRIANGLE, GlobalColor.RED), false, false);
|
||||
ToastLog("T-BL-"+ShapeColor.LookupResult(GlobalShape.TRIANGLE, GlobalColor.BLACK), false, false);
|
||||
ToastLog("T-G-"+ShapeColor.LookupResult(GlobalShape.TRIANGLE, GlobalColor.GREEN), false, false);
|
||||
ToastLog("T-BU-"+ShapeColor.LookupResult(GlobalShape.TRIANGLE, GlobalColor.BLUE), false, false);
|
||||
ToastLog("T-C-"+ShapeColor.LookupResult(GlobalShape.TRIANGLE, GlobalColor.CYAN), false, false);
|
||||
ToastLog("T-P-"+ShapeColor.LookupResult(GlobalShape.TRIANGLE, GlobalColor.PURPLE), false, false);
|
||||
ToastLog("T-W-"+ShapeColor.LookupResult(GlobalShape.TRIANGLE, GlobalColor.WHITE), false, false);
|
||||
ToastLog("T-Y-"+ShapeColor.LookupResult(GlobalShape.TRIANGLE, GlobalColor.YELLOW), false, false);*/
|
||||
|
||||
return encoder.GenerateCommand(Commands.COLOR_SHAPE_SUCCESS, a, b, c);
|
||||
}
|
||||
}*/
|
||||
//形状颜色识别改用开源AI模型
|
||||
ShapeDetector detector = new ShapeDetector();
|
||||
detector.shapePicProcess(currImage);
|
||||
ShapeColorResult result = detector.GetAllResult();
|
||||
ToastLog(result.toString(), false, true);
|
||||
return encoder.GenerateCommand();
|
||||
}
|
||||
|
||||
//识别车牌
|
||||
@@ -401,7 +402,7 @@ public class MainActivity extends AppCompatActivity
|
||||
private byte[] RecognizeTrafficSign()
|
||||
{
|
||||
CommandEncoder encoder = new CommandEncoder();
|
||||
GlobalSignType type = TrafficSign.SignRecognize(currImage);
|
||||
/*GlobalSignType type = TrafficSign.SignRecognize(currImage);
|
||||
if (type == GlobalSignType.Failure)
|
||||
return encoder.GenerateCommand(Commands.TRAFFIC_SIGN_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||
else
|
||||
@@ -429,7 +430,11 @@ public class MainActivity extends AppCompatActivity
|
||||
break;
|
||||
}
|
||||
return encoder.GenerateCommand();
|
||||
}
|
||||
}*/
|
||||
//交通标志改用开源AI模型识别
|
||||
String result = TS_Detector.processImage(currImage);
|
||||
ToastLog("Traffic Sign: " + result, false, true);
|
||||
return encoder.GenerateCommand();
|
||||
}
|
||||
|
||||
//识别静态文本
|
||||
@@ -468,6 +473,16 @@ public class MainActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
//识别车型
|
||||
private byte[] RecognizeVehicle()
|
||||
{
|
||||
CommandEncoder encoder = new CommandEncoder();
|
||||
//使用开源AI模型识别车型
|
||||
String result = VID_Detector.processImage(currImage);
|
||||
ToastLog("Vehicle: " + result, false, true);
|
||||
return encoder.GenerateCommand();
|
||||
}
|
||||
|
||||
//数组转字符串,仅用于调试输出
|
||||
private String ByteArray2String(byte[] arr)
|
||||
{
|
||||
@@ -570,19 +585,47 @@ public class MainActivity extends AppCompatActivity
|
||||
context.findViewById(R.id.btn_start_qr).setOnClickListener(view ->
|
||||
{
|
||||
ToastLog("QR Code Started", false, false);
|
||||
ToastLog("QR Result: " + ByteArray2String(RecognizeQrCode()), false, false);
|
||||
//默认情况下使用黑白二维码识别
|
||||
ToastLog("QR Result: " + ByteArray2String(RecognizeQrCode(false, GlobalColor.INVALIDATE)), false, false);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_start_red_qr).setOnClickListener(view ->
|
||||
{
|
||||
ToastLog("QR Code Started (Red)", false, false);
|
||||
//针对彩色二维码单独测试二维码识别
|
||||
ToastLog("QR (Red) Result: " + ByteArray2String(RecognizeQrCode(true, GlobalColor.RED)), false, false);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_start_green_qr).setOnClickListener(view ->
|
||||
{
|
||||
ToastLog("QR Code Started (Green)", false, false);
|
||||
//针对彩色二维码单独测试二维码识别
|
||||
ToastLog("QR (Green) Result: " + ByteArray2String(RecognizeQrCode(true, GlobalColor.GREEN)), false, false);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_start_yellow_qr).setOnClickListener(view ->
|
||||
{
|
||||
ToastLog("QR Code Started (Yellow)", false, false);
|
||||
//针对彩色二维码单独测试二维码识别
|
||||
ToastLog("QR (Yellow) Result: " + ByteArray2String(RecognizeQrCode(true, GlobalColor.YELLOW)), false, false);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_start_light).setOnClickListener(view ->
|
||||
{
|
||||
ToastLog("Traffic Light Started", false, false);
|
||||
ToastLog("TL Result: " + ByteArray2String(RecognizeTrafficLight()), false, false);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_start_color_shape).setOnClickListener(view ->
|
||||
{
|
||||
ToastLog("Color Shape Started", false, false);
|
||||
ToastLog("CS Result: " + ByteArray2String(RecognizeShapeColor()), false, false);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_start_car_id).setOnClickListener(view ->
|
||||
@@ -591,12 +634,14 @@ public class MainActivity extends AppCompatActivity
|
||||
Thread th_debug = new Thread(this::RecognizeCarID);
|
||||
th_debug.start();
|
||||
ToastLog("CID Finished", false, false);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_start_sign).setOnClickListener(view ->
|
||||
{
|
||||
ToastLog("Traffic Sign Started", false, false);
|
||||
ToastLog("TS Result: " + ByteArray2String(RecognizeTrafficSign()), false, false);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_start_ocr).setOnClickListener(view ->
|
||||
@@ -604,6 +649,7 @@ public class MainActivity extends AppCompatActivity
|
||||
ToastLog("OCR Started", false, false);
|
||||
Thread th_debug = new Thread(this::OCRRecognizeText);
|
||||
th_debug.start();
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_tft_page_down).setOnClickListener(view ->
|
||||
@@ -611,6 +657,7 @@ public class MainActivity extends AppCompatActivity
|
||||
CommandEncoder encoder = new CommandEncoder();
|
||||
dtc_client.ThreadSend(encoder.GenerateCommand(Commands.TFT_PAGE_DOWN, (byte) 0, (byte) 0, (byte) 0));
|
||||
ToastLog("TFT Page Down Command Send.", false, true);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_movement_control).setOnClickListener(view -> startActivity(new Intent(this, MovementController.class)));
|
||||
@@ -629,18 +676,21 @@ public class MainActivity extends AppCompatActivity
|
||||
detector.shapePicProcess(currImage);
|
||||
ShapeColorResult result = detector.GetAllResult();
|
||||
ToastLog(result.toString(), false, false);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_os_trafficsign).setOnClickListener(view ->
|
||||
{
|
||||
String res = TS_Detector.processImage(currImage);
|
||||
ToastLog("Traffic Sign Result: " + res, false, false);
|
||||
context.finish();
|
||||
});
|
||||
|
||||
context.findViewById(R.id.btn_os_vehicle).setOnClickListener(view ->
|
||||
{
|
||||
String res = TS_Detector.processImage(currImage);
|
||||
ToastLog("Vehicle Result: " + res, false, false);
|
||||
context.finish();
|
||||
});
|
||||
}
|
||||
//----------------------------------------到此处终止----------------------------------------
|
||||
|
||||
@@ -22,6 +22,8 @@ import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.uns.maincar.R;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
//Android的存储权限的获取
|
||||
public class PermissionGetter extends AppCompatActivity
|
||||
{
|
||||
@@ -72,6 +74,8 @@ public class PermissionGetter extends AppCompatActivity
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_permission_getter);
|
||||
|
||||
Objects.requireNonNull(getSupportActionBar()).setTitle("主车远端服务程序 - 权限获取");
|
||||
|
||||
GetExternalStoragePrivilege();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ import com.uns.maincar.R;
|
||||
import com.uns.maincar.constants.Commands;
|
||||
import com.uns.maincar.constants.Flags;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class RaceTasks extends AppCompatActivity
|
||||
{
|
||||
|
||||
@@ -49,6 +51,8 @@ public class RaceTasks extends AppCompatActivity
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_race_tasks);
|
||||
|
||||
Objects.requireNonNull(getSupportActionBar()).setTitle("主车远端服务程序 - 比赛任务");
|
||||
|
||||
if (Parent == null)
|
||||
{
|
||||
Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show();
|
||||
|
||||
@@ -15,6 +15,8 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.uns.maincar.R;
|
||||
import com.uns.maincar.constants.Flags;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class SingleFunctionTest extends AppCompatActivity
|
||||
{
|
||||
|
||||
@@ -27,6 +29,8 @@ public class SingleFunctionTest extends AppCompatActivity
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_single_function_test);
|
||||
|
||||
Objects.requireNonNull(getSupportActionBar()).setTitle("主车远端服务程序 - 独立测试");
|
||||
|
||||
if (Parent == null)
|
||||
{
|
||||
Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show();
|
||||
|
||||
@@ -215,4 +215,34 @@
|
||||
android:layout_weight="1"
|
||||
android:text="开源\n车型识别" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_start_red_qr"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="3dp"
|
||||
android:layout_weight="1"
|
||||
android:text="红色\n二维码识别" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_start_green_qr"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="3dp"
|
||||
android:layout_weight="1"
|
||||
android:text="绿色\n二维码识别" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_start_yellow_qr"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="3dp"
|
||||
android:layout_weight="1"
|
||||
android:text="黄色\n二维码识别" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
Reference in New Issue
Block a user