数字近景工业摄影测量中Schneider编码标志的自动生成程序
前言
在数字近景摄影测量中,最关键的图像间的匹配。但是由于工业测量现场复杂的背景和被测物体表面没有足够的特征,应用在双目视觉中基于关键点匹配的算法在效率、精度、准确率等方面,大多不能满足需求。于是在工业数字近景测量中需要人工设置的靶标点作为关键点进行匹配。
人工设置的靶标有很多种,目前最主要的点分布型,同心圆环型,非几何特征型。本文利用程序实现了同心圆环型中Schneider C .T设计的靶标的自动生成。
Schneider 编码方案介绍
它由中心圆和同心编码环带组成,编码环带按照角度均分为10份,每份36°,每一份可以称为亮环带或者暗环带,相应的二进制码为1或者0,“1”表示该位上有编码点,“0”表示该位上没有编码点,由于编码环带并没有规定起始点,以任意一个编码点为起始位置,按顺时针方向读取编码环带的码值, 可以组成长度为 10的二进制序列,对这个二进制序列进行循环移位,选取其中数值最小的二进制序列作为该靶标的码值。
自动生成编码代码
该方法采用opencv实现画圆和部分圆环。
主函数
int main()
{
//8位的二进制数循环移位
vector<int> queue;
uint16_t isexist[40000] = { 0 };
vector<int> result;
int piccount = 0;
for (uint16_t i = 1; i < pow(2,BIT); i++)
{
//判断该数是否在队列
if(isexist[i] == 1)
continue;
//把该数对应的8个移位数据放入队列
for (int j = 0; j < BIT; j++)
isexist[move(i, j, BIT)] = 1;
//用该数生成一个图片
int picsize = 1000;
int radius1 = 150;
int radius2 = 300;
int radius3 = 400;
Mat temp = Mat::zeros(Size(picsize, picsize), CV_8UC1);
if(INVERT)
bitwise_not(temp, temp);
//先画一个圆
if (INVERT)
circle(temp, Point(picsize / 2, picsize / 2), radius1, CV_RGB(0, 0, 0), -1);
else
circle(temp, Point(picsize / 2, picsize / 2), radius1, CV_RGB(0, 0, 255), -1);
//画BIT个扇形
for (int k = 0; k < BIT; k++)
{
if (i & (unsigned int)(pow(2, k)))
{
vector<vector<Point>> contours;
vector<Point> contour;
Point p0;
float range = 360.0 / BIT;
for (int angle = range * k; angle <= range*(k + 1); angle = angle + 1)
{
p0 = Point(picsize / 2 + radius2 * cos(angle / 180.0*3.1416),
picsize / 2 + radius2 * sin(angle / 180.0*3.1416));
contour.push_back(p0);
}
for (int angle = range * (k + 1); angle >= range*k; angle = angle - 1)
{
p0 = Point(picsize / 2 + radius3 * cos(angle / 180.0*3.1416),
picsize / 2 + radius3 * sin(angle / 180.0*3.1416));
contour.push_back(p0);
}
contours.push_back(contour);
if(INVERT)
drawContours(temp, contours, -1, CV_RGB(0, 0, 0), -1);
else
drawContours(temp, contours, -1, CV_RGB(0, 0, 255), -1);
}
}
//保存图片
string filename;
if (INVERT)
{
createDirectory(to_string(BIT) + "反/");
filename = to_string(BIT) + "反/" + to_string(i) + ".bmp";
}
else
{
createDirectory(to_string(BIT) + "/");
filename = to_string(BIT) + "/" + to_string(i) + ".bmp";
}
//保存图片
imwrite(filename, temp);
piccount++;
result.push_back(i);
}
cout << piccount << endl;
for (int i = 0; i < result.size(); i++)
cout << result[i] << "\t";
cout << endl;
while(1);
return 0;
}
调用的函数1:循环移位操作
/*
参数说明:
number:要移位的数
c:要移的位数
bit:总共有几位,默认为8
*/
uint16_t move(uint16_t number, uint8_t c, uint8_t bit = 8)
{
//首先判读输入的是否合理
if (number < 0 && number >= pow(2, bit))
cout << "输入的参数1:" << number << "不合理!" << endl;
if (c >= bit)
cout << "输入的参数2" << c << "不合理!" << endl;
uint16_t a = number;
uint16_t left = 0;//存储左移之后的结果
uint16_t right = 0;//存储右移之后的结果
uint16_t mask = pow(2, bit) - 1;
right = ((a & mask) >> c) & mask;
left = ((a & mask) << (bit - c)) & mask;
uint16_t result;
result = left | right;
return result;
}
调用的函数2:创建目录函数
bool createDirectory(const std::string folder)
{
std::string folder_builder;
std::string sub;
sub.reserve(folder.size());
for (auto it = folder.begin(); it != folder.end(); ++it)
{
//cout << *(folder.end()-1) << endl;
const char c = *it;
sub.push_back(c);
if (c == '\\' || it == folder.end() - 1)
{
folder_builder.append(sub);
if (0 != ::_access(folder_builder.c_str(), 0))
{
// this folder not exist
if (0 != ::_mkdir(folder_builder.c_str()))
{
// create failed
return false;
}
}
sub.clear();
}
}
return true;
}
生成图片展示
4位编码
8位编码
12位编码(不是全部)
程序下载
程序工程目录截图
下载地址:
https://download.youkuaiyun.com/download/iamqianrenzhan/10562068