add colored qr code
This commit is contained in:
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/app/src/main/cpp/colored_qr_detect/colored_qr_decode.cpp" charset="GBK" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -165,6 +165,21 @@ add_library( # Sets the name of the library.
|
|||||||
lib_hyper_lpr/src/SegmentationFreeRecognizer.cpp
|
lib_hyper_lpr/src/SegmentationFreeRecognizer.cpp
|
||||||
lib_hyper_lpr/javaWarpper.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
|
# Searches for a specified prebuilt library and stores the path as a
|
||||||
# variable. Because CMake includes system libraries in the search path by
|
# variable. Because CMake includes system libraries in the search path by
|
||||||
# default, you only need to specify the name of the public NDK library
|
# 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}
|
${OpenCV_LIBS}
|
||||||
${jnigraphics-lib}
|
${jnigraphics-lib}
|
||||||
${log-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;
|
int max_count = 0;
|
||||||
std::string color_name = "null";
|
Colors::CVColor max_color;
|
||||||
Colors::ColorCount counter = basic_color_counter;
|
Colors::ColorCount counter = basic_color_counter;
|
||||||
if (img.empty())
|
if (img.empty())
|
||||||
return color_name;
|
return std_color_white;
|
||||||
for (int r = 0; r < img.rows; r++)
|
for (int r = 0; r < img.rows; r++)
|
||||||
{
|
{
|
||||||
for (int c = 0; c < img.cols; c++)
|
for (int c = 0; c < img.cols; c++)
|
||||||
@@ -46,17 +46,42 @@ namespace uns
|
|||||||
counter[std_color_white]++;
|
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;
|
continue;
|
||||||
if (ele.second > max_count)
|
if (ele.second > max_count)
|
||||||
{
|
{
|
||||||
|
max_color = ele.first;
|
||||||
max_count = ele.second;
|
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::map<Colors::CVColor, std::string> color_name_map =
|
||||||
{
|
{
|
||||||
{ std_color_red, "red" },
|
{std_color_red, "red" },
|
||||||
{ std_color_green, "green"},
|
{std_color_green, "green"},
|
||||||
{ std_color_blue, "blue"},
|
{std_color_blue, "blue"},
|
||||||
{ std_color_yellow, "yellow"},
|
{std_color_yellow, "yellow"},
|
||||||
{ std_color_purple, "purple"},
|
{std_color_purple, "purple"},
|
||||||
{ std_color_cyan, "cyan"},
|
{std_color_cyan, "cyan"},
|
||||||
{ std_color_black, "black"},
|
{std_color_black, "black"},
|
||||||
{ std_color_white, "white"},
|
{std_color_white, "white"},
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
bool MuchLarger(int a, int b, double rate);
|
bool MuchLarger(int a, int b, double rate);
|
||||||
|
|
||||||
public:
|
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_DATA = (byte) 0xD9;
|
||||||
public static byte OCR_TEXT_FINISH = (byte) 0xE9;
|
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 RUN_SINGE_TASK = (byte) 0xA0;
|
||||||
public static byte TASK_NUMBER_0 = 0x00;
|
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_TRAFFIC_SIGN = (byte) 0xA6;
|
||||||
public static final byte RECEIVE_TEXT_OCR = (byte) 0xA7;
|
public static final byte RECEIVE_TEXT_OCR = (byte) 0xA7;
|
||||||
public static final byte RECEIVE_OCR_DATA_OK = (byte) 0xB7;
|
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 Bitmap GetNextQR();
|
||||||
private static native boolean ProcessQR(Bitmap image);
|
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)
|
public static boolean BeginQRDecode(Bitmap img)
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||||||
import com.uns.maincar.R;
|
import com.uns.maincar.R;
|
||||||
import com.uns.maincar.constants.Flags;
|
import com.uns.maincar.constants.Flags;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class DebugPage extends AppCompatActivity
|
public class DebugPage extends AppCompatActivity
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -27,6 +29,8 @@ public class DebugPage extends AppCompatActivity
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_debug_page);
|
setContentView(R.layout.activity_debug_page);
|
||||||
|
|
||||||
|
Objects.requireNonNull(getSupportActionBar()).setTitle("主车远端服务程序 - 调试");
|
||||||
|
|
||||||
if (Parent == null)
|
if (Parent == null)
|
||||||
{
|
{
|
||||||
Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show();
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
|
|
||||||
package com.uns.maincar.gui;
|
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.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
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.Commands;
|
||||||
import com.uns.maincar.constants.Flags;
|
import com.uns.maincar.constants.Flags;
|
||||||
import com.uns.maincar.constants.Flags.TrafficLightColors;
|
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.CarLicense;
|
||||||
|
import com.uns.maincar.cpp_interface.ColoredQRDecoder;
|
||||||
import com.uns.maincar.cpp_interface.EnvTest;
|
import com.uns.maincar.cpp_interface.EnvTest;
|
||||||
import com.uns.maincar.cpp_interface.MainCarAES;
|
import com.uns.maincar.cpp_interface.MainCarAES;
|
||||||
import com.uns.maincar.cpp_interface.OCR;
|
import com.uns.maincar.cpp_interface.OCR;
|
||||||
import com.uns.maincar.cpp_interface.QRDecoder;
|
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.TrafficLight;
|
||||||
import com.uns.maincar.cpp_interface.TrafficSign;
|
|
||||||
import com.uns.maincar.data_type.ShapeColorResult;
|
import com.uns.maincar.data_type.ShapeColorResult;
|
||||||
import com.uns.maincar.open_source.shape.ShapeDetector;
|
import com.uns.maincar.open_source.shape.ShapeDetector;
|
||||||
import com.uns.maincar.open_source.traffic_sign.YoloV5_tfLite_TSDetector;
|
import com.uns.maincar.open_source.traffic_sign.YoloV5_tfLite_TSDetector;
|
||||||
@@ -173,7 +176,8 @@ public class MainActivity extends AppCompatActivity
|
|||||||
break;
|
break;
|
||||||
//收到QR指令,开始识别二维码,回传识别成功的数据
|
//收到QR指令,开始识别二维码,回传识别成功的数据
|
||||||
case Commands.RECEIVE_QR:
|
case Commands.RECEIVE_QR:
|
||||||
byte[] cmd = RecognizeQrCode();
|
//默认情况下使用黑白二维码识别
|
||||||
|
byte[] cmd = RecognizeQrCode(false, GlobalColor.INVALIDATE);
|
||||||
if (cmd[2] == Commands.QR_FAILED)
|
if (cmd[2] == Commands.QR_FAILED)
|
||||||
dtc_client.Send(cmd);
|
dtc_client.Send(cmd);
|
||||||
else
|
else
|
||||||
@@ -204,6 +208,8 @@ public class MainActivity extends AppCompatActivity
|
|||||||
case Commands.RECEIVE_TEXT_OCR:
|
case Commands.RECEIVE_TEXT_OCR:
|
||||||
OCRRecognizeText();
|
OCRRecognizeText();
|
||||||
break;
|
break;
|
||||||
|
case Commands.RECEIVE_VEHICLE:
|
||||||
|
dtc_client.Send(RecognizeVehicle());
|
||||||
//收到未知指令,回传异常指令,表示无法解析当前指令
|
//收到未知指令,回传异常指令,表示无法解析当前指令
|
||||||
default:
|
default:
|
||||||
CommandEncoder error = new CommandEncoder();
|
CommandEncoder error = new CommandEncoder();
|
||||||
@@ -249,6 +255,16 @@ public class MainActivity extends AppCompatActivity
|
|||||||
return MainCarAES.CalcAES(validate_result);
|
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()
|
private byte[] SystemStatusCommand()
|
||||||
{
|
{
|
||||||
@@ -260,9 +276,11 @@ public class MainActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
//识别二维码
|
//识别二维码
|
||||||
private byte[] RecognizeQrCode()
|
private byte[] RecognizeQrCode(boolean colored, GlobalColor target_color)
|
||||||
{
|
{
|
||||||
CommandEncoder encoder = new CommandEncoder();
|
CommandEncoder encoder = new CommandEncoder();
|
||||||
|
if (!colored)
|
||||||
|
{
|
||||||
ArrayList<String> qr_result = new ArrayList<>();
|
ArrayList<String> qr_result = new ArrayList<>();
|
||||||
if (!QRDecoder.BeginQRDecode(currImage))
|
if (!QRDecoder.BeginQRDecode(currImage))
|
||||||
return encoder.GenerateCommand(Commands.QR_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
return encoder.GenerateCommand(Commands.QR_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||||
@@ -276,6 +294,23 @@ public class MainActivity extends AppCompatActivity
|
|||||||
return ProcessQRData(qr_result);
|
return ProcessQRData(qr_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//识别交通灯
|
//识别交通灯
|
||||||
private byte[] RecognizeTrafficLight()
|
private byte[] RecognizeTrafficLight()
|
||||||
@@ -300,54 +335,20 @@ public class MainActivity extends AppCompatActivity
|
|||||||
private byte[] RecognizeShapeColor()
|
private byte[] RecognizeShapeColor()
|
||||||
{
|
{
|
||||||
CommandEncoder encoder = new CommandEncoder();
|
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);
|
return encoder.GenerateCommand(Commands.COLOR_SHAPE_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
byte a = 0, b = 0, c = 0;
|
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);
|
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()
|
private byte[] RecognizeTrafficSign()
|
||||||
{
|
{
|
||||||
CommandEncoder encoder = new CommandEncoder();
|
CommandEncoder encoder = new CommandEncoder();
|
||||||
GlobalSignType type = TrafficSign.SignRecognize(currImage);
|
/*GlobalSignType type = TrafficSign.SignRecognize(currImage);
|
||||||
if (type == GlobalSignType.Failure)
|
if (type == GlobalSignType.Failure)
|
||||||
return encoder.GenerateCommand(Commands.TRAFFIC_SIGN_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
return encoder.GenerateCommand(Commands.TRAFFIC_SIGN_FAILED, (byte) 0, (byte) 0, (byte) 0);
|
||||||
else
|
else
|
||||||
@@ -429,7 +430,11 @@ public class MainActivity extends AppCompatActivity
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return encoder.GenerateCommand();
|
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)
|
private String ByteArray2String(byte[] arr)
|
||||||
{
|
{
|
||||||
@@ -570,19 +585,47 @@ public class MainActivity extends AppCompatActivity
|
|||||||
context.findViewById(R.id.btn_start_qr).setOnClickListener(view ->
|
context.findViewById(R.id.btn_start_qr).setOnClickListener(view ->
|
||||||
{
|
{
|
||||||
ToastLog("QR Code Started", false, false);
|
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 ->
|
context.findViewById(R.id.btn_start_light).setOnClickListener(view ->
|
||||||
{
|
{
|
||||||
ToastLog("Traffic Light Started", false, false);
|
ToastLog("Traffic Light Started", false, false);
|
||||||
ToastLog("TL Result: " + ByteArray2String(RecognizeTrafficLight()), false, false);
|
ToastLog("TL Result: " + ByteArray2String(RecognizeTrafficLight()), false, false);
|
||||||
|
context.finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
context.findViewById(R.id.btn_start_color_shape).setOnClickListener(view ->
|
context.findViewById(R.id.btn_start_color_shape).setOnClickListener(view ->
|
||||||
{
|
{
|
||||||
ToastLog("Color Shape Started", false, false);
|
ToastLog("Color Shape Started", false, false);
|
||||||
ToastLog("CS Result: " + ByteArray2String(RecognizeShapeColor()), false, false);
|
ToastLog("CS Result: " + ByteArray2String(RecognizeShapeColor()), false, false);
|
||||||
|
context.finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
context.findViewById(R.id.btn_start_car_id).setOnClickListener(view ->
|
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);
|
Thread th_debug = new Thread(this::RecognizeCarID);
|
||||||
th_debug.start();
|
th_debug.start();
|
||||||
ToastLog("CID Finished", false, false);
|
ToastLog("CID Finished", false, false);
|
||||||
|
context.finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
context.findViewById(R.id.btn_start_sign).setOnClickListener(view ->
|
context.findViewById(R.id.btn_start_sign).setOnClickListener(view ->
|
||||||
{
|
{
|
||||||
ToastLog("Traffic Sign Started", false, false);
|
ToastLog("Traffic Sign Started", false, false);
|
||||||
ToastLog("TS Result: " + ByteArray2String(RecognizeTrafficSign()), false, false);
|
ToastLog("TS Result: " + ByteArray2String(RecognizeTrafficSign()), false, false);
|
||||||
|
context.finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
context.findViewById(R.id.btn_start_ocr).setOnClickListener(view ->
|
context.findViewById(R.id.btn_start_ocr).setOnClickListener(view ->
|
||||||
@@ -604,6 +649,7 @@ public class MainActivity extends AppCompatActivity
|
|||||||
ToastLog("OCR Started", false, false);
|
ToastLog("OCR Started", false, false);
|
||||||
Thread th_debug = new Thread(this::OCRRecognizeText);
|
Thread th_debug = new Thread(this::OCRRecognizeText);
|
||||||
th_debug.start();
|
th_debug.start();
|
||||||
|
context.finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
context.findViewById(R.id.btn_tft_page_down).setOnClickListener(view ->
|
context.findViewById(R.id.btn_tft_page_down).setOnClickListener(view ->
|
||||||
@@ -611,6 +657,7 @@ public class MainActivity extends AppCompatActivity
|
|||||||
CommandEncoder encoder = new CommandEncoder();
|
CommandEncoder encoder = new CommandEncoder();
|
||||||
dtc_client.ThreadSend(encoder.GenerateCommand(Commands.TFT_PAGE_DOWN, (byte) 0, (byte) 0, (byte) 0));
|
dtc_client.ThreadSend(encoder.GenerateCommand(Commands.TFT_PAGE_DOWN, (byte) 0, (byte) 0, (byte) 0));
|
||||||
ToastLog("TFT Page Down Command Send.", false, true);
|
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)));
|
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);
|
detector.shapePicProcess(currImage);
|
||||||
ShapeColorResult result = detector.GetAllResult();
|
ShapeColorResult result = detector.GetAllResult();
|
||||||
ToastLog(result.toString(), false, false);
|
ToastLog(result.toString(), false, false);
|
||||||
|
context.finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
context.findViewById(R.id.btn_os_trafficsign).setOnClickListener(view ->
|
context.findViewById(R.id.btn_os_trafficsign).setOnClickListener(view ->
|
||||||
{
|
{
|
||||||
String res = TS_Detector.processImage(currImage);
|
String res = TS_Detector.processImage(currImage);
|
||||||
ToastLog("Traffic Sign Result: " + res, false, false);
|
ToastLog("Traffic Sign Result: " + res, false, false);
|
||||||
|
context.finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
context.findViewById(R.id.btn_os_vehicle).setOnClickListener(view ->
|
context.findViewById(R.id.btn_os_vehicle).setOnClickListener(view ->
|
||||||
{
|
{
|
||||||
String res = TS_Detector.processImage(currImage);
|
String res = TS_Detector.processImage(currImage);
|
||||||
ToastLog("Vehicle Result: " + res, false, false);
|
ToastLog("Vehicle Result: " + res, false, false);
|
||||||
|
context.finish();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//----------------------------------------到此处终止----------------------------------------
|
//----------------------------------------到此处终止----------------------------------------
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import androidx.core.content.ContextCompat;
|
|||||||
|
|
||||||
import com.uns.maincar.R;
|
import com.uns.maincar.R;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
//Android的存储权限的获取
|
//Android的存储权限的获取
|
||||||
public class PermissionGetter extends AppCompatActivity
|
public class PermissionGetter extends AppCompatActivity
|
||||||
{
|
{
|
||||||
@@ -72,6 +74,8 @@ public class PermissionGetter extends AppCompatActivity
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_permission_getter);
|
setContentView(R.layout.activity_permission_getter);
|
||||||
|
|
||||||
|
Objects.requireNonNull(getSupportActionBar()).setTitle("主车远端服务程序 - 权限获取");
|
||||||
|
|
||||||
GetExternalStoragePrivilege();
|
GetExternalStoragePrivilege();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import com.uns.maincar.R;
|
|||||||
import com.uns.maincar.constants.Commands;
|
import com.uns.maincar.constants.Commands;
|
||||||
import com.uns.maincar.constants.Flags;
|
import com.uns.maincar.constants.Flags;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class RaceTasks extends AppCompatActivity
|
public class RaceTasks extends AppCompatActivity
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -49,6 +51,8 @@ public class RaceTasks extends AppCompatActivity
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_race_tasks);
|
setContentView(R.layout.activity_race_tasks);
|
||||||
|
|
||||||
|
Objects.requireNonNull(getSupportActionBar()).setTitle("主车远端服务程序 - 比赛任务");
|
||||||
|
|
||||||
if (Parent == null)
|
if (Parent == null)
|
||||||
{
|
{
|
||||||
Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show();
|
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.R;
|
||||||
import com.uns.maincar.constants.Flags;
|
import com.uns.maincar.constants.Flags;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class SingleFunctionTest extends AppCompatActivity
|
public class SingleFunctionTest extends AppCompatActivity
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -27,6 +29,8 @@ public class SingleFunctionTest extends AppCompatActivity
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_single_function_test);
|
setContentView(R.layout.activity_single_function_test);
|
||||||
|
|
||||||
|
Objects.requireNonNull(getSupportActionBar()).setTitle("主车远端服务程序 - 独立测试");
|
||||||
|
|
||||||
if (Parent == null)
|
if (Parent == null)
|
||||||
{
|
{
|
||||||
Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Context is null!", Toast.LENGTH_SHORT).show();
|
||||||
|
|||||||
@@ -215,4 +215,34 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="开源\n车型识别" />
|
android:text="开源\n车型识别" />
|
||||||
</LinearLayout>
|
</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>
|
</LinearLayout>
|
||||||
+3
-3
@@ -11,7 +11,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": -124854207
|
"memoizedHashCode": 816914465
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 949559604
|
"memoizedHashCode": 1891328276
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -39,6 +39,6 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": -1251864759
|
"memoizedHashCode": -310096087
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
+3
-3
@@ -11,7 +11,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": -1065851171
|
"memoizedHashCode": -124082499
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 176408592
|
"memoizedHashCode": 1118177264
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -39,6 +39,6 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": -139244825
|
"memoizedHashCode": 802523847
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
+5
@@ -1,2 +1,7 @@
|
|||||||
# C/C++ build system timings
|
# C/C++ build system timings
|
||||||
|
|
||||||
|
# C/C++ build system timings
|
||||||
|
generate_cxx_metadata
|
||||||
|
create-invalidation-state 12ms
|
||||||
|
generate_cxx_metadata completed in 16ms
|
||||||
|
|
||||||
|
|||||||
+5
@@ -198,3 +198,8 @@ generate_cxx_metadata completed in 26ms
|
|||||||
|
|
||||||
# C/C++ build system timings
|
# C/C++ build system timings
|
||||||
|
|
||||||
|
# C/C++ build system timings
|
||||||
|
generate_cxx_metadata
|
||||||
|
create-invalidation-state 24ms
|
||||||
|
generate_cxx_metadata completed in 29ms
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -11,7 +11,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 1119238981
|
"memoizedHashCode": 2061007653
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": -1243038600
|
"memoizedHashCode": -301269928
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -39,6 +39,6 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": -444239237
|
"memoizedHashCode": 497529435
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
+3
-3
@@ -11,7 +11,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 1041076311
|
"memoizedHashCode": 1982844983
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 286425208
|
"memoizedHashCode": 1228193880
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -39,6 +39,6 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 704135946
|
"memoizedHashCode": 1645904618
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
Binary file not shown.
+3
-3
@@ -11,7 +11,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 783740077
|
"memoizedHashCode": 2049212457
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 431825513
|
"memoizedHashCode": 1697297893
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -39,6 +39,6 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": -779738141
|
"memoizedHashCode": 485734239
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -178,3 +178,15 @@ create_cxx_tasks
|
|||||||
create-initial-cxx-model completed in 89ms
|
create-initial-cxx-model completed in 89ms
|
||||||
create_cxx_tasks completed in 90ms
|
create_cxx_tasks completed in 90ms
|
||||||
|
|
||||||
|
# C/C++ build system timings
|
||||||
|
create_cxx_tasks
|
||||||
|
create-initial-cxx-model
|
||||||
|
create-module-model
|
||||||
|
create-cmake-model 36ms
|
||||||
|
create-module-model completed in 38ms
|
||||||
|
create-module-model
|
||||||
|
create-cmake-model 38ms
|
||||||
|
create-module-model completed in 40ms
|
||||||
|
create-initial-cxx-model completed in 94ms
|
||||||
|
create_cxx_tasks completed in 94ms
|
||||||
|
|
||||||
|
|||||||
@@ -1151,3 +1151,15 @@ create_cxx_tasks
|
|||||||
create-initial-cxx-model completed in 85ms
|
create-initial-cxx-model completed in 85ms
|
||||||
create_cxx_tasks completed in 87ms
|
create_cxx_tasks completed in 87ms
|
||||||
|
|
||||||
|
# C/C++ build system timings
|
||||||
|
create_cxx_tasks
|
||||||
|
create-initial-cxx-model
|
||||||
|
create-module-model
|
||||||
|
create-cmake-model 39ms
|
||||||
|
create-module-model completed in 41ms
|
||||||
|
create-module-model
|
||||||
|
create-cmake-model 36ms
|
||||||
|
create-module-model completed in 38ms
|
||||||
|
create-initial-cxx-model completed in 97ms
|
||||||
|
create_cxx_tasks completed in 99ms
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 1692822936
|
"memoizedHashCode": -1660375688
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": -1809956257
|
"memoizedHashCode": -868187585
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": -1105495064
|
"memoizedHashCode": -163726392
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 757319006
|
"memoizedHashCode": 1699087678
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": -135370576
|
"memoizedHashCode": 806398096
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level_": 0,
|
"level_": 0,
|
||||||
@@ -81,6 +81,6 @@
|
|||||||
"fieldsDescending": {}
|
"fieldsDescending": {}
|
||||||
},
|
},
|
||||||
"memoizedSize": -1,
|
"memoizedSize": -1,
|
||||||
"memoizedHashCode": 200609643
|
"memoizedHashCode": 1142378315
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
Reference in New Issue
Block a user