外面的项目需要做一个工业读表的功能,并给发来了百度飞桨的案例链接https://www.paddlepaddle.org.cn/tutorials/projectdetail/3387933。基本的要求是在百度飞桨的基础上进行修改即可,因此主要的工作是修改读表的部分。
由于百度的教程非常详细,所以代码配置问题在此处省略,需要注意的是环境配置必须完全按照教程使用CUDA10.2,否则会导致编译错误,此处只对如何修改读表做出总结。
修改表盘读取范围
打开meter_reader.cpp可以看到63行处有GetMeterReading方法,ctrl+左键点入该方法的所在位置,是在src/reader_postprocess.cpp文件的第233行,而此处也正如教程开始的图片所示。
bool GetMeterReading(
const std::vector<std::vector<uint8_t>> &seg_label_maps,
std::vector<float> *readings) {
for (auto i = 0; i < seg_label_maps.size(); i++) {
std::vector<uint8_t> rectangle_meter;
CircleToRectangle(seg_label_maps[i], &rectangle_meter);
std::vector<int> line_scale;
std::vector<int> line_pointer;
RectangleToLine(rectangle_meter, &line_scale, &line_pointer);
std::vector<int> binaried_scale;
MeanBinarization(line_scale, &binaried_scale);
std::vector<int> binaried_pointer;
MeanBinarization(line_pointer, &binaried_pointer);
std::vector<float> scale_location;
LocateScale(binaried_scale, &scale_location);
float pointer_location;
LocatePointer(binaried_pointer, &pointer_location);
MeterResult result;
GetRelativeLocation(
scale_location, pointer_location, &result);
float reading;
CalculateReading(result, &reading);
readings->push_back(reading);
}
return true;
}
首先将语义分割的结果经过腐蚀处理后输入,之后使用CircleToRectangle将环形表盘展开为矩形图像,这个方法是修改的关键,因为涉及到这个矩形是从何处开始截取的,即表盘的起始点。该方法在前面的57行:
bool CircleToRectangle(
const std::vector<uint8_t> &seg_label_map,
std::vector<uint8_t> *rectangle_meter) {
float theta;
int rho;
int image_x;
int image_y;
*rectangle_meter =
std::vector<uint8_t> (RECTANGLE_WIDTH * RECTANGLE_HEIGHT, 0);
for (int row = 0; row < RECTANGLE_HEIGHT; row++) {
for (int col = 0; col < RECTANGLE_WIDTH; col++) {
theta = PI * 2 / RECTANGLE_WIDTH * (col + 1);
rho = CIRCLE_RADIUS - row - 1;
int y = static_cast<int>(CIRCLE_CENTER[0] + rho * cos(theta) + 0.5);
int x = static_cast<int>(CIRCLE_CENTER[1] - rho * sin(theta) + 0.5);
(*rectangle_meter)[row * RECTANGLE_WIDTH + col] =
seg_label_map[y * METER_SHAPE[1] + x];
}
}
return true;
}
如果想要将表盘起始点改为数值向上,只需要将y坐标改为:
int y = static_cast<int>(CIRCLE_CENTER[0] - rho * cos(theta) + 0.5);
int x = static_cast<int>(CIRCLE_CENTER[1] + rho * sin(theta) + 0.5);
使得y坐标由小变大再变小,x坐标先变大再变小,自绘示例图对照图片的坐标系便很好理解。
修改读表数值
在修改完读表范围后,读表数值的修改相对简单一些,首先下面是对meter_config.cpp的标注,后续的更改也是基于这个文件。
#include "meter_reader/include/meter_config.h"
std::vector<int> METER_SHAPE = {512, 512};
std::vector<int> CIRCLE_CENTER = {256, 256};
int CIRCLE_RADIUS = 250;
float PI = 3.1415926536;
int RECTANGLE_HEIGHT = 120;
int RECTANGLE_WIDTH = 1570;
int TYPE_THRESHOLD = 40;
std::vector<MeterConfig> METER_CONFIG = {
MeterConfig(25.0f/50.0f, 25.0f, "(MPa)"),
MeterConfig(1.6f/32.0f, 1.6f, "(MPa)"),
MeterConfig(100.0f/100.0f, 100.0f, "(Kg)")
};
std::map<std::string, uint8_t> SEG_CNAME2CLSID = {
{"background", 0}, {"pointer", 1}, {"scale", 2}
};
根据GetMeterReading方法可知,CalculateReading即最终读表的数值,在reader_postprocess.cpp的201行。
bool CalculateReading(const MeterResult &result,
float *reading) {
if (result.num_scales_ > TYPE_THRESHOLD) {
*reading = result.pointed_scale_ * METER_CONFIG[0].scale_interval_value_;
} else {
*reading = result.pointed_scale_ * METER_CONFIG[1].scale_interval_value_;
}
return true;
此处TYPE_THRESHOLD为刻度线根数,如果有多个不同类型的表盘则至少要保证其刻度线根数不一样,从而可以添加多个TYPE_THRESHOLD,并添加多种类型的表盘。如:
bool CalculateReading(const MeterResult &result,
float *reading) {
if (result.num_scales_ > TYPE_THRESHOLD[0] && result.num_scales_ < TYPE_THRESHOLD[1]) {
*reading = result.pointed_scale_ * METER_CONFIG[0].scale_interval_value_;
} else if (result.num_scales_ > TYPE_THRESHOLD[1] && result.num_scales_ < TYPE_THRESHOLD[2]){
*reading = result.pointed_scale_ * METER_CONFIG[1].scale_interval_value_;
} else {
*reading = result.pointed_scale_ * METER_CONFIG[2].scale_interval_value_;
}
return true;
小结
得益于百度飞桨内训练好的目标检测和语义分割模型,使得工作的复杂度大大降低。如果需要读取的表盘和刻度与案例相差甚远,则需要重新训练检测和语义分割的模型。此外,该方案需要保证表盘的清晰可见,使用网络高噪点图像做测试时,该方法的读取效果并不佳。
基于该案例做提升的方法有许多,如利用OCR自动获取新表盘的最大量程,使用较小的检测模型进行目标检测以提升速度,通过TCP传输读数做进一步处理等,本文就不再赘述了。
Original: https://blog.csdn.net/Pariya_Official/article/details/124576687
Author: 帕里亚
Title: 百度飞桨-基于CV的工业读表案例(修改读表范围和数值)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/641718/
转载文章受原作者版权保护。转载请注明原作者出处!