代码拉取完成,页面将自动刷新
#include "find_decode.h"
//#define Debug
//#define lengthThres 50
//#define lengthThres1 100
//#define lengthThres2 37
ver_pair vps[100];
int L=0;
/**
@brief 从分组线段中搜索出约成90度夹角的线段对
@param [in] seg_mat 分组线段
@param [in] seg_cnt 分组线段计数
@param [in] lthThres1 线段长度下限
@param [in] lthThres2 线段长度上限
@param [out] vps 线段对数组
@param [out] m 线段对计数
*/
void findVertcialLinesFromSeg_mat(line_template seg_mat[][segNumLimit/2], int seg_cnt[], int lthThres1,
int lthThres2, ver_pair vps[], int &m)
{
int cntL =0, cntB=0, cntBl=0, cntBr=0, cntBll=0, cntBrr=0;
int v=0, vl=0, vr=0, vll=0, vrr=0;
//float seg_theta =0.0;
float segL_lth =0.0, segB_lth =0.0;
const float deviAngleThres =6.0; //角度偏差阈值
line_template *sp = NULL, *cp = NULL;
bool b1,b2,b3,b4;
m=0;
for(int i=0; i<=30; i++)
{
v = (i+30)%60;
vl = (i+29)%60;
vr = (i+31)%60;
vll = (i+28)%60;
vrr = (i+32)%30;
cntL = seg_cnt[i];
cntB = seg_cnt[v];
cntBl = seg_cnt[vl];
cntBr = seg_cnt[vr];
cntBll = seg_cnt[vll];
cntBrr = seg_cnt[vrr];
if(cntL && (cntBll || cntBl || cntB ||cntBr || cntBrr))
{
for(int j=0; j <cntL; j++)
{
sp = &seg_mat[i][j];
segL_lth = sqrt((sp->s.col-sp->e.col)*(sp->s.col-sp->e.col) + (sp->s.row-sp->e.row)*(sp->s.row-sp->e.row));
if(segL_lth >= lthThres1 && segL_lth <= lthThres2)
{
for(int k=0; k <cntB; k++)
{
cp = &seg_mat[v][k];
if(fabs(fabs(sp->dir-cp->dir)-90.0) <= deviAngleThres){
segB_lth = sqrt((cp->s.col-cp->e.col)*(cp->s.col-cp->e.col) + (cp->s.row-cp->e.row)*(cp->s.row-cp->e.row));
b1 = (abs(sp->s.col-cp->s.col)+abs(sp->s.row-cp->s.row)) <= 2*lthThres1;
b2 = (abs(sp->s.col-cp->e.col)+abs(sp->s.row-cp->e.row)) <= 2*lthThres1;
b3 = (abs(sp->e.col-cp->s.col)+abs(sp->e.row-cp->s.row)) <= 2*lthThres1;
b4 = (abs(sp->e.col-cp->e.col)+abs(sp->e.row-cp->e.row)) <= 2*lthThres1;
if(segB_lth >= lthThres1 && segB_lth <= lthThres2 && (b1||b2||b3||b4)){
vps[m].L = *sp;
vps[m].B = *cp;
m++;
}
}
}
for(int k=0; k <cntBl; k++)
{
cp = &seg_mat[vl][k];
if(fabs(fabs(sp->dir-cp->dir)-90.0) <=deviAngleThres){
segB_lth = sqrt((cp->s.col-cp->e.col)*(cp->s.col-cp->e.col) + (cp->s.row-cp->e.row)*(cp->s.row-cp->e.row));
b1 = (abs(sp->s.col-cp->s.col)+abs(sp->s.row-cp->s.row)) <= 2*lthThres1;
b2 = (abs(sp->s.col-cp->e.col)+abs(sp->s.row-cp->e.row)) <= 2*lthThres1;
b3 = (abs(sp->e.col-cp->s.col)+abs(sp->e.row-cp->s.row)) <= 2*lthThres1;
b4 = (abs(sp->e.col-cp->e.col)+abs(sp->e.row-cp->e.row)) <= 2*lthThres1;
if(segB_lth >= lthThres1 && segB_lth <= lthThres2 && (b1||b2||b3||b4)){
vps[m].L = *sp;
vps[m].B = *cp;
m++;
}
}
}
for(int k=0; k <cntBr; k++)
{
cp = &seg_mat[vr][k];
if(fabs(fabs(sp->dir-cp->dir)-90.0) <=deviAngleThres){
segB_lth = sqrt((cp->s.col-cp->e.col)*(cp->s.col-cp->e.col) + (cp->s.row-cp->e.row)*(cp->s.row-cp->e.row));
b1 = (abs(sp->s.col-cp->s.col)+abs(sp->s.row-cp->s.row)) <= 2*lthThres1;
b2 = (abs(sp->s.col-cp->e.col)+abs(sp->s.row-cp->e.row)) <= 2*lthThres1;
b3 = (abs(sp->e.col-cp->s.col)+abs(sp->e.row-cp->s.row)) <= 2*lthThres1;
b4 = (abs(sp->e.col-cp->e.col)+abs(sp->e.row-cp->e.row)) <= 2*lthThres1;
if(segB_lth >= lthThres1 && segB_lth <= lthThres2 && (b1||b2||b3||b4)){
vps[m].L = *sp;
vps[m].B = *cp;
m++;
}
}
}
for(int k=0; k<cntBll; k++)
{
cp = &seg_mat[vll][k];
if(fabs(fabs(sp->dir-cp->dir)-90.0) <=deviAngleThres){
segB_lth = sqrt((cp->s.col-cp->e.col)*(cp->s.col-cp->e.col) + (cp->s.row-cp->e.row)*(cp->s.row-cp->e.row));
b1 = (abs(sp->s.col-cp->s.col)+abs(sp->s.row-cp->s.row)) <= 2*lthThres1;
b2 = (abs(sp->s.col-cp->e.col)+abs(sp->s.row-cp->e.row)) <= 2*lthThres1;
b3 = (abs(sp->e.col-cp->s.col)+abs(sp->e.row-cp->s.row)) <= 2*lthThres1;
b4 = (abs(sp->e.col-cp->e.col)+abs(sp->e.row-cp->e.row)) <= 2*lthThres1;
if(segB_lth >= lthThres1 && segB_lth <= lthThres2 && (b1||b2||b3||b4)){
vps[m].L = *sp;
vps[m].B = *cp;
m++;
}
}
}
for(int k=0; k<cntBrr; k++)
{
cp = &seg_mat[vrr][k];
if(fabs(fabs(sp->dir-cp->dir)-90.0) <=deviAngleThres){
segB_lth = sqrt((cp->s.col-cp->e.col)*(cp->s.col-cp->e.col) + (cp->s.row-cp->e.row)*(cp->s.row-cp->e.row));
b1 = (abs(sp->s.col-cp->s.col)+abs(sp->s.row-cp->s.row)) <= 2*lthThres1;
b2 = (abs(sp->s.col-cp->e.col)+abs(sp->s.row-cp->e.row)) <= 2*lthThres1;
b3 = (abs(sp->e.col-cp->s.col)+abs(sp->e.row-cp->s.row)) <= 2*lthThres1;
b4 = (abs(sp->e.col-cp->e.col)+abs(sp->e.row-cp->e.row)) <= 2*lthThres1;
if(segB_lth >= lthThres1 && segB_lth <= lthThres2 && (b1||b2||b3||b4)){
vps[m].L = *sp;
vps[m].B = *cp;
m++;
}
}
}
}
}
}
}
//将vps尺度扩大一倍,作用于原始图像
for(int i=0; i<m; i++)
{
vps[i].L.s.col *=2;
vps[i].L.s.row *=2;
vps[i].L.e.col *=2;
vps[i].L.e.row *=2;
vps[i].B.s.col *=2;
vps[i].B.s.row *=2;
vps[i].B.e.col *=2;
vps[i].B.e.row *=2;
}
}
#define testBlackThres (grayThres)
#define testWhiteThres (grayThres)
/**
@brief 从直角对中寻找出L的左边和底边
**@brief DM码图像结构
|口 口 口
| 口
L | 口
|口 口
| 口 口
——————————
B
**@param [in] image 原始图像
**@param [in] auxSubIndex 遍历图像辅助矩阵
**@param [in] width 图像宽
**@param [in] height 图像高
**@param [out] vps 如上图,储存找到的DM的L线段、B线段
**@param [in] lthThres1 线段长度下限
*/
int find_LB_fromVerticalPairs(uchar image[], uint auxSubIndex[],ushort width, ushort height,
ver_pair vps[], int m, int lthThres1)
{
//static Hposition_f L1,L2;
position crossP, leftP, bottomP, midP, testP_in, testP_ex;
position_f newCrossP_f;
//position_f newCrossP;
float lthTemp =0.0;
uchar detDir;
for(int i=0; i<m; i++)
{
vps[i].Lparam = cross_ip_fhp(vps[i].L.s, vps[i].L.e);
vps[i].Bparam = cross_ip_fhp(vps[i].B.s, vps[i].B.e);
//printf("s=(%d,%d), e=(%d,%d), L1=(%f,%f,%f)\n",vps[i].L.s.col, vps[i].L.s.row,vps[i].L.e.col, vps[i].L.e.row, L1.x, L1.y, L1.scale);
//printf("s=(%d,%d), e=(%d,%d), L2=(%f,%f,%f)\n",vps[i].B.s.col, vps[i].B.s.row,vps[i].B.e.col, vps[i].B.e.row, L2.x, L2.y, L2.scale);
//fflush(stdout);
crossP = cross_fhp_ip(vps[i].Lparam, vps[i].Bparam);//初步确定L B交点
if(manhattan(vps[i].L.s, crossP) > manhattan(vps[i].L.e, crossP)) //确定除L上除交点的外一点:左点
leftP = vps[i].L.s;
else
leftP = vps[i].L.e;
if(manhattan(vps[i].B.s, crossP) > manhattan(vps[i].B.e, crossP)) //确定除B上除交点的外一点:底点
bottomP = vps[i].B.s;
else
bottomP = vps[i].B.e;
midP.col = (leftP.col + bottomP.col)/2; //确定 左点 底点连线中点
midP.row = (leftP.row + bottomP.row)/2;
lthTemp = sqrt((midP.col-crossP.col)*(midP.col-crossP.col)+(midP.row-crossP.row)*(midP.row-crossP.row));
testP_in.col = round(crossP.col + (midP.col-crossP.col)*5/lthTemp); //确定内测试点
testP_in.row = round(crossP.row + (midP.row-crossP.row)*5/lthTemp);
testP_ex.col = round(crossP.col - (midP.col-crossP.col)*5/lthTemp); //确定外测试点
testP_ex.row = round(crossP.row - (midP.row-crossP.row)*5/lthTemp);
if(meanGray(image, auxSubIndex, testP_in)<testBlackThres && meanGray(image, auxSubIndex, testP_ex)>testWhiteThres){
//if(meanGray(image, auxSubIndex, testP_in)<(grayThres-10) && meanGray(image, auxSubIndex, testP_ex)>grayThres){
//printf("L.s=(%d,%d), L.e=(%d,%d)\n",vps[i].L.s.col, vps[i].L.s.row, vps[i].L.e.col, vps[i].L.e.row);
//printf("B.s=(%d,%d), B.e=(%d,%d)\n",vps[i].B.s.col, vps[i].B.s.row, vps[i].B.e.col, vps[i].B.e.row);
vps[i].L.s = crossP;
//vps[i].L.e = leftP;
vps[i].L.e = calacE(crossP, leftP, L_lth);//根据L边的长度和起点计算两边终点
vps[i].B.s = crossP;
//vps[i].B.e = bottomP;
vps[i].B.e = calacE(crossP, bottomP, L_lth);
//printf("L is %d.\n",i);
//printf("leftP=(%d,%d), midP=(%d,%d), bottomP=(%d,%d)\n",leftP.col, leftP.row, midP.col, midP.row, bottomP.col, bottomP.row);
//fflush(stdout);
adjustLB(leftP, midP, bottomP, crossP, vps[i]);
detDir = calacDetDir(vps[i].L, vps[i].LquadC, true);
adjustAngle(image, auxSubIndex, width, height, vps[i].L, vps[i].Lparam, detDir);
detDir = calacDetDir(vps[i].B, vps[i].BquadC, false);
adjustAngle(image, auxSubIndex, width, height, vps[i].B, vps[i].Bparam, detDir);//对left和bottom的角度进行调整
newCrossP_f = cross_fhp_fp(vps[i].Lparam, vps[i].Bparam);
crossP.col = (int)round(newCrossP_f.x);
crossP.row = (int)round(newCrossP_f.y);
vps[i].L.s = crossP;
vps[i].B.s = crossP;
vps[i].CrossP_f = newCrossP_f;
// printf("crossP=(%d,%d)\n",crossP.col, crossP.row);
// printf("newCrossP=(%f,%f)\n",newCrossP_f.x, newCrossP_f.y);
// fflush(stdout);
//if(1){
if(adjustLBEndpoint(image, auxSubIndex, width, height, vps[i])){
//printf("bottomP_f=(%f,%f).\n",vps[i].bottomP_f.x, vps[i].bottomP_f.y);
//printf("leftP_f=(%f,%f).\n",vps[i].leftP_f.x, vps[i].leftP_f.y);
//fflush(stdout);
detDir = calacDetDir(vps[i].L, vps[i].LquadC, true);
adjustAngle(image, auxSubIndex, width, height, vps[i].L, vps[i].Lparam, detDir);
detDir = calacDetDir(vps[i].B, vps[i].BquadC, false);
adjustAngle(image, auxSubIndex, width, height, vps[i].B, vps[i].Bparam, detDir);
newCrossP_f = cross_fhp_fp(vps[i].Lparam, vps[i].Bparam);
crossP.col = (int)round(newCrossP_f.x);
crossP.row = (int)round(newCrossP_f.y);
vps[i].L.s = crossP;
vps[i].B.s = crossP;
vps[i].CrossP_f = newCrossP_f;
if(adjustLBEndpoint(image, auxSubIndex, width, height, vps[i])){
float lastL_lth = L_lth;
uchar lastGrayThres = grayThres;
//L_lth = updateL_lth(vps[i].CrossP_f, vps[i].leftP_f, vps[i].bottomP_f);
if(DmRegionCheck(image, auxSubIndex, width, height, vps[i], L_lth, grayThres, agvPoseFromDM)){
//L_lth = updateL_lth(vps[i].CrossP_f, vps[i].leftP_f, vps[i].bottomP_f);
cout<< L_lth <<" "<< (int)grayThres << endl;
samPS[19] = testP_in;
samPS[20] = testP_ex;
return i;
}else{
L_lth = lastL_lth;
grayThres = lastGrayThres;
}
// printf("crossP=(%f,%f)\n",vps[i].CrossP_f.x, vps[i].CrossP_f.y);
// printf("bottomP_f=(%f,%f).\n",vps[i].bottomP_f.x, vps[i].bottomP_f.y);
// printf("leftP_f=(%f,%f).\n",vps[i].leftP_f.x, vps[i].leftP_f.y);
}else{
cout << "adjust endpoint failed."<<endl;
}
}else{
cout << "adjust endpoint failed."<<endl;
}
}else
cout<< "find no DM bar"<<endl;
}
return -1;
}
/**
@brief 检查当前约成90度夹角的线段对所包含的区域\n
是否属于DM码数据区,如果属于,则进行解码,和\n
解算相机位姿
@param [in] image 原始输入图像
@param [in] auxSubIndex 用于遍历图像的辅助计算数组
@param [in] width 图像宽
@param [in] height 图像高
@param [in] vp 约成90度夹角的线段对
@param [in] L_lth DM LB边长度
@param binaryThres 二值化阈值
@param [out] POSE 相机位姿
@retval false 不属于
@retval true 解算成功
*/
bool DmRegionCheck(uchar image[], uint auxSubIndex[],ushort width, ushort height,
ver_pair &vp, float L_lth, uchar &binaryThres, pose &POSE)
{
uchar grayTest[19];
memset(grayTest,0,19);
float scale = L_lth/20,theta=0.0;
int grayThres=0;
position tempPos={0,0};
signed char testSum=0;
//cout<<"vp.L.dir ="<<vp.L.dir<<" vp.LquadC"<<(int)vp.LquadC<<endl;
//float temp = sqrt(vp.Lparam.x*vp.Lparam.x+vp.Lparam.y*vp.Lparam.y);
//float cosTheta = fabs(vp.Lparam.y)/temp;
//float sinTheta = -vp.Lparam.x/temp;
if(vp.LquadC==2)
theta = 180 + vp.L.dir;
else if(vp.LquadC==0)
theta = -180 + vp.L.dir;
else
theta = vp.L.dir;
float cosTheta = cos(theta*3.1416/180);
float sinTheta = sin(theta*3.1416/180);
for(int i=0;i<19;i++){
tempPos.col = (int)round(vp.CrossP_f.x + locP[i].col*scale*cosTheta - locP[i].row*scale*sinTheta);
tempPos.row = (int)round(vp.CrossP_f.y + locP[i].col*scale*sinTheta + locP[i].row*scale*cosTheta);
//grayTest[i] = image[auxSubIndex[tempPos.row] + tempPos.col];
if(tempPos.col <=0 || tempPos.col>=(width-1) || tempPos.row <=0 || tempPos.row >=(height-1))
return false;
grayTest[i] = meanGray(image, auxSubIndex, tempPos);
grayThres += grayTest[i];
samPS[i] = tempPos;
}
for(int i=1; i<19; i++,i++)
{
grayTest[i] = grayTest[i] >binaryThres;
grayTest[i-1] = grayTest[i-1] >binaryThres;
testSum +=grayTest[i]-grayTest[i-1];
//printf("%d, %d\n",grayTest[i-1], grayTest[i]);
}
if(testSum <=7){
//cout<<(int)testSum<<endl;
return false;
}else{
grayThres /=19;
binaryThres = grayThres; //更新灰度阈值
//cout << "update gray thres:"<<(int)binaryThres<<endl;
}
uchar num[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
for(int i=0; i<64; i++)
{
tempPos.col = (int)round(vp.CrossP_f.x + DatP[i].col*scale*cosTheta-DatP[i].row*scale*sinTheta);
tempPos.row = (int)round(vp.CrossP_f.y + DatP[i].col*scale*sinTheta+DatP[i].row*scale*cosTheta);
if(tempPos.col <=0 || tempPos.col>=(width-1) || tempPos.row <=0 || tempPos.row >=(height-1))
return false;
num[i/8] |= (meanGray(image, auxSubIndex, tempPos) <binaryThres) <<(7-i%8);
//samPS[i] = tempPos;
}
POSE.x = num[0]-130;
POSE.y = num[1]-130;
POSE.theta = theta;
//坐标系变换
POSE.x = POSE.x + 0.034/L_lth*(320.5 - vp.CrossP_f.x); //这里要乘以 系数 = 实际长度/L_lth
POSE.y = POSE.y + 0.034/L_lth*(240.5 - vp.CrossP_f.y);
POSE.theta = -POSE.theta;
return true;
}
/**
@brief 确定LB边的端点
@param leftP L边的端点(非与B边交点)
@param midP 辅助判断点
@param bottomP B边的端点(非与L边交点)
@param crossP LB边交点
@param vp 约成90度夹角的线段对
*/
void adjustLB(position &leftP, position &midP, position &bottomP, position &crossP, ver_pair &vp)
{
vp.LquadC = (leftP.col >= crossP.col) + ((leftP.row >= crossP.row)<<1);
vp.BquadC = (bottomP.col >= crossP.col) + ((bottomP.row >= crossP.row)<<1);
uchar LquadM = (leftP.col >= midP.col) + ((leftP.row >= midP.row)<<1);
//uchar BquadM = (bottomP.col >= midP.col) + ((bottomP.row >= midP.row)<<1);
//qDebug()<<"Mquad="<<Mquad<<", Lquad="<<Lquad<<", Bquad="<<Bquad<<".";
//printf("LquadC=%d, BquadC=%d, LquadM=%d\n",vp.LquadC, vp.BquadC, LquadM);
bool isLine1Left = false;
if(3 == vp.LquadC){
if(2 == vp.BquadC)
isLine1Left = true;
else if(3 == vp.BquadC && 1 == LquadM)
isLine1Left = true;
}else if(2 == vp.LquadC){
if(0 == vp.BquadC)
isLine1Left = true;
else if(2 == vp.BquadC && 3 == LquadM)
isLine1Left = true;
}else if(0 == vp.LquadC){
if(1 == vp.BquadC)
isLine1Left = true;
else if(0 == vp.BquadC && 2 == LquadM)
isLine1Left = true;
}else if(1 == vp.LquadC){
if(3 == vp.BquadC)
isLine1Left = true;
else if(1 == vp.BquadC && 0 == LquadM)
isLine1Left = true;
}
if(!isLine1Left){
Hposition_f temp;
temp = vp.Lparam;
vp.Lparam = vp.Bparam;
vp.Bparam = temp;
line_template temp2;
temp2 = vp.L;
vp.L = vp.B;
vp.B = temp2;
uchar temp3;
temp3 = vp.BquadC;
vp.BquadC = vp.LquadC;
vp.LquadC = temp3;
}
}
/**
@brief 根据先验的边的长度和起点计算边终点
@param [in] S 线段边起点
@param [in] oldE 旧的线段的终点
@param [in] lth 先验的边长度
@return 返回重算过的线段的终点
*/
position calacE(position S, position oldE, float lth)
{
if(lth>0){
position newE;
float k=0.0,temp=0.0;
short diff_Y = oldE.row - S.row;
short diff_X = oldE.col - S.col;
if(0==diff_X){
newE.col = oldE.col;
if(diff_Y >0)
newE.row = S.row + lth;
else
newE.row = S.row - lth;
}else{
k = float(diff_Y)/float(diff_X);
temp = sqrt(lth*lth/(1+k*k));
if(diff_X>0){
newE.col = S.col + temp;
newE.row = S.row + int(k*temp);
}else{
newE.col = S.col - temp;
newE.row = S.row - int(k*temp);
}
// if(diff_Y>0)
// newE.row = S.row + k*abs(newE.col - S.col);
// else
// newE.row = S.row - k*abs(newE.col - S.col);
}
// printf("k=%f, temp=%f, lth=%f, S=(%d,%d), OldE=(%d,%d),newE=(%d,%d)\n",k, temp, lth, S.col, S.row, oldE.col, oldE.row, newE.col, newE.row);
// fflush(stdout);
return newE;
}else
return oldE;
}
float updateL_lth(position_f &C, position_f &L, position_f &B)
{
double lth = sqrt((L.x-C.x)*(L.x-C.x)+(L.y-C.y)*(L.y-C.y));
lth += sqrt((B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y));
// printf("%lf\n",lth/2);
// fflush(stdout);
return lth/2;
}
/**
@brief 为获取亚像素精度,调整垂直直线对的终点(已知直线对相交点和方向)
@param [in] image 原始图像
@param [in] auxSubIndex 图像遍历辅助矩阵
@param [in] width 图像宽
@param [in] height 图像高
@param vp 待调整直线对(结构体)
@param retval false 调整失败
@param retval true 调整成功
*/
bool adjustLBEndpoint(uchar image[], uint auxSubIndex[], ushort width, ushort height, ver_pair &vp)
{
short diff_X = vp.B.e.col - vp.B.s.col;
short diff_Y = vp.B.e.row - vp.B.s.row;
position detectP;
const uchar gap =1;
short cntUpper = abs(diff_X) > abs(diff_Y) ? abs(diff_X)/gap : abs(diff_Y)/gap;
bool breakB_Flag = false, breakL_Flag = false;
float temp;
//printf("%d \n",cntUpper);
//fflush(stdout);
// for(int i=0; i<100; i++){
// samPS[i].col =0;
// samPS[i].row =0;
// }
for(int i=cntUpper-2; i <=2*cntUpper; i++)//注意这里从-2开始
//for(int i=-2; i <=cntUpper; i++)//注意这里从-2开始
{
if(abs(diff_X)>abs(diff_Y))
{
if(diff_X >0.0)
//detectP.col = vp.B.e.col + i*gap; //使用终点作为起始点检测点位置错误,还没看出原因
temp = vp.CrossP_f.x + i*gap;
else
//detectP.col = vp.B.e.col - i*gap;
temp = vp.CrossP_f.x - i*gap;
//detectP.row = vp.B.e.row + (int)round((vp.B.e.col-detectP.col)*vp.Bparam.x/vp.Bparam.y);
detectP.row = (int)round(vp.CrossP_f.y + (vp.CrossP_f.x-temp)*vp.Bparam.x/vp.Bparam.y);
detectP.col = (int)round(temp);
}else{
if(diff_Y>0.0)
//detectP.row = vp.B.e.row + i*gap;
temp = (int)round(vp.CrossP_f.y + i*gap);
else
//detectP.row = vp.B.e.row - i*gap;
temp = (int)round(vp.CrossP_f.y - i*gap);
//detectP.col = vp.B.e.col + (int)round((vp.B.e.row-detectP.row)*vp.Bparam.y/vp.Bparam.x);
detectP.col = (int)round(vp.CrossP_f.x + (vp.CrossP_f.y-temp)*vp.Bparam.y/vp.Bparam.x);
detectP.row = (int)round(temp);
}
// printf("(%d,%d) ",detectP.col,detectP.row);
// fflush(stdout);
if(detectP.row <0 || detectP.row >=height || detectP.col <0 || detectP.col >= width)//已经到达图像边缘,剩余的点也不满足要求
{
// printf("adjust endpoint %d valid points.\n",i-cntUpper+2);
// fflush(stdout);
break;
}
//samPS[i+2-cntUpper] = detectP;
//samPS[i+2] = detectP;
if(verify(image, auxSubIndex, width, height, detectP,false, grayThres, 1)){
if(abs(diff_X)>abs(diff_Y)){
if(diff_X>0)
vp.bottomP_f.x = detectP.col-3*gap;
else
vp.bottomP_f.x = detectP.col+3*gap;
vp.bottomP_f.y = vp.CrossP_f.y + (vp.CrossP_f.x-vp.bottomP_f.x)*vp.Bparam.x/vp.Bparam.y;
}else{
if(diff_Y>0)
vp.bottomP_f.y = detectP.row-3*gap;
else
vp.bottomP_f.y = detectP.row+3*gap;
vp.bottomP_f.x = vp.CrossP_f.x + (vp.CrossP_f.y-vp.bottomP_f.y)*vp.Bparam.y/vp.Bparam.x;
}
vp.B.e.col = (int)round(vp.bottomP_f.x);
vp.B.e.row = (int)round(vp.bottomP_f.y);
breakB_Flag = true;
// printf("adjust endpoint %d valid points.\n",i-cntUpper+3);
// fflush(stdout);
break;
}
}
// for(int i=0; i<sampNum; i++){
// printf("(%d,%d) ",samPS[i].col,samPS[i].row);
// }
// printf("\n");
// fflush(stdout);
diff_X = vp.L.e.col - vp.L.s.col;
diff_Y = vp.L.e.row - vp.L.s.row;
cntUpper = abs(diff_X) > abs(diff_Y) ? abs(diff_X)/gap : abs(diff_Y)/gap;
for(int i=cntUpper-2; i <=2*cntUpper; i++)//注意这里从-2开始
//for(int i=-2; i <=cntUpper; i++)//注意这里从-2开始
{
if(abs(diff_X)>abs(diff_Y))
{
if(diff_X >0.0)
//detectP.col = vp.B.e.col + i*gap; //使用终点作为起始点检测点位置错误,还没看出原因
temp = vp.CrossP_f.x + i*gap;
else
//detectP.col = vp.B.e.col - i*gap;
temp = vp.CrossP_f.x - i*gap;
//detectP.row = vp.B.e.row + (int)round((vp.B.e.col-detectP.col)*vp.Bparam.x/vp.Bparam.y);
detectP.row = (int)round(vp.CrossP_f.y + (vp.CrossP_f.x-temp)*vp.Lparam.x/vp.Lparam.y);
detectP.col = (int)round(temp);
}else{
if(diff_Y>0.0)
//detectP.row = vp.B.e.row + i*gap;
temp = (int)round(vp.CrossP_f.y + i*gap);
else
//detectP.row = vp.B.e.row - i*gap;
temp = (int)round(vp.CrossP_f.y - i*gap);
//detectP.col = vp.B.e.col + (int)round((vp.B.e.row-detectP.row)*vp.Bparam.y/vp.Bparam.x);
detectP.col = (int)round(vp.CrossP_f.x + (vp.CrossP_f.y-temp)*vp.Lparam.y/vp.Lparam.x);
detectP.row = (int)round(temp);
}
// printf("(%d,%d) ",detectP.col,detectP.row);
// fflush(stdout);
if(detectP.row <0 || detectP.row >=height || detectP.col <0 || detectP.col >= width)//已经到达图像边缘,剩余的点也不满足要求
{
// printf("adjust endpoint %d valid points.\n",i-cntUpper+2);
// fflush(stdout);
break;
}
//samPS[i+2-cntUpper] = detectP;
//samPS[i+2] = detectP;
if(verify(image, auxSubIndex, width, height, detectP, false, grayThres, 1)){
if(abs(diff_X)>abs(diff_Y)){
if(diff_X>0)
vp.leftP_f.x = detectP.col-3*gap;
else
vp.leftP_f.x = detectP.col+3*gap;
vp.leftP_f.y = vp.CrossP_f.y + (vp.CrossP_f.x-vp.leftP_f.x)*vp.Lparam.x/vp.Lparam.y;
}else{
if(diff_Y>0)
vp.leftP_f.y = detectP.row-3*gap;
else
vp.leftP_f.y = detectP.row+3*gap;
vp.leftP_f.x = vp.CrossP_f.x + (vp.CrossP_f.y-vp.leftP_f.y)*vp.Lparam.y/vp.Lparam.x;
}
vp.L.e.col = (int)round(vp.leftP_f.x);
vp.L.e.row = (int)round(vp.leftP_f.y);
breakL_Flag = true;
break;
}
}
if(breakB_Flag && breakL_Flag)
return true;
else
return false;
}
/**
@brief 根据线段和所属象限,计算L边或者B边的方向编码
@param [in] l 线段
@param [in] quad 线段在图像坐标中的象限
@param [in] isLeftFlag l是否属于DM定位区左边
@param 方向编码
*/
uchar calacDetDir(line_template &l, uchar quad, bool isLeftFlag)
{
short diff_X = l.e.col-l.s.col;
short diff_Y = l.e.row-l.s.row;
uchar detDir;
if(abs(diff_X)>abs(diff_Y)){
if(2==quad || 0==quad)
detDir = 0x00 | (0x0F & (!isLeftFlag));
else
detDir = 0x00 | (0x0F & isLeftFlag);
}else{
if(0==quad || 1==quad)
detDir = 0x10 | (0x0F & isLeftFlag);
else
detDir = 0x10 | (0x0F & (!isLeftFlag));
}
// printf("detDir=%d, quad=%d, isLeftFlag=%d\n", detDir, quad, isLeftFlag);
// fflush(stdout);
//printf("detDir = %d %d %d %d \n",0x00 | (0x0F & (!isLeftFlag)), 0x00 | (0x0F & isLeftFlag), 0x10 | (0x0F & isLeftFlag), detDir = 0x10 | (0x0F & (!isLeftFlag)));
return detDir;
}
/**
@brief 根据图像边缘信息,对直线的角度进行调整
@param [in] image 原始图像
@param [in] auxSubIndex 辅助矩阵
@param [in] width 图像宽
@param [in] height 图像高
@param [in] l 线段(结构体)
@param [in] lparam 线段齐次参数(浮点)
@param [in] detDir 方向编码
*/
void adjustAngle(uchar image[], uint auxSubIndex[], ushort width, ushort height,
line_template &l, Hposition_f &lparam, uchar detDir)
{
bool aa;
short diff_X = l.e.col-l.s.col;
short diff_Y = l.e.row-l.s.row;
const uchar sampGap =3;
uchar sampNum;
if(abs(diff_X)>abs(diff_Y))
sampNum = abs(diff_X)/3-2;
else
sampNum = abs(diff_Y)/3-2;
int k=0;
for(int i=0; i<100; i++){
samPS[i].col =0;
samPS[i].row =0;
}
// printf("diff_X = %d, diff_Y = %d, sample points num = %d\n",diff_X, diff_Y, sampNum);
// fflush(stdout);
samplePoints(l.s, l.e, sampNum, sampGap, samPS);
// printf("line.s=(%d,%d), line.e=(%d,%d)\n", l.s.col, l.s.row, l.e.col, l.e.row);
// fflush(stdout);
// for(int i=0; i<sampNum; i++){
// printf("(%d,%d) ",samPS[i].col,samPS[i].row);
// }
// printf("\n");
for(int i=0; i<sampNum; i++){
aa = verify(image, auxSubIndex, width, height, samPS[i], detDir, grayThres, 0);
// printf("%d / %d\n",i, sampNum);
// fflush(stdout);
if(aa){
samPS[k] = samPS[i];
k++;
}
}
// printf("%d valid points.\n",k);
// fflush(stdout);
//最小二乘法求解新角度
LSnewAngle(samPS, k, l, lparam);
}
/*寻找周围过渡点,拟合直线*/
//signed char coor5X5[16][2] = {{0,2},{-1,2},{-2,2},{-2,1},{-2,0},{-2,-1},{-2,-2},{-1,-2},{0,-2},{1,-2},{2,-2},{2,-1},{2,0},{2,1},{2,2},{1,2}};
/**
@brief 验证目标点是否是边缘点或者空白点
@param image 原始图像
@param auxSubIndex 图像遍历辅助矩阵
@param width 图像宽
@param height 图像宽
@param dstP 目标点
@param detDir 检测点局部区域横纵方向,0:竖向 1:横向
@param binaryThres 局部二值化阈值
@param pointType 检测点类型:0:边缘点,1:空白点
@retval true 是边缘点
@retval false 不是边缘点
*/
bool verify(uchar image[], uint auxSubIndex[], ushort width, ushort height, position &dstP,
uchar detDir,uchar binaryThres, uchar pointType)
{
//static uchar recoArr[32];
uchar segNum=0, segLth=0, idx_s=0;
int i, j, margin=0,margin1=0;
//float mid1=0, mid2=0;
position p;
bool breakFlag = false;
//static int k;
if(0==pointType){
if((detDir >>4)==0){
margin =0;
if((detDir & 0x0F)==1)
margin1 = 7;
else
margin1 = -7;
//margin1 = 7;
}else{
if((detDir & 0x0F)==1)
margin = 7;
else
margin = -7;
//margin = 7;
margin1 = 0;
}
}else if(1==pointType){
margin =0;
margin1 =0;
}
// printf("detDir=%d, margin=%d, margin1=%d\n",detDir, margin, margin1);
// fflush(stdout);
for( i =dstP.col-margin; ;)
{
//if(i <(margin+1) || i >=(width-margin-1))
if(i <=1 || i >=(width-2))
break; //mark:"break" relpaces "continue";
for( j =dstP.row -margin1; ;)
{
//if(j<(margin1+1) || j >=(height-margin1-1))
if(j<=1 || j >=(height-2))
break;
p.col =i;
p.row =j;
// printf("%d, %d\n",i,j);
// fflush(stdout);
// if(1==pointType){
// printf("%d\n",k);
// samPS[k++] = p;
// }
//calcSegNumSegLth(image, auxSubIndex, p, binaryThres, 5, segNum, segLth, idx_s);
if(0==pointType){ //边缘点
calcSegNumSegLth(image, auxSubIndex, p, binaryThres, 5, segNum, segLth, idx_s);
if(segNum ==1 && segLth >=7 && segLth <=9){
breakFlag = true;
dstP = p;
break;
}
}else if(1==pointType){ //空白点
calcSegNumSegLth(image, auxSubIndex, p, binaryThres, 5, segNum, segLth, idx_s);
if(segNum ==0)
//if(segNum ==1 && segLth >=4 && segLth <=7)
{
//mid1 = (float)idx_s + (float)segLth/2 - 0.5;
//calcSegNumSegLth(image, auxSubIndex, p, binaryThres, 3, segNum, segLth, idx_s); //直角点检测需要加以3X3模板辅助
//if(segNum ==0)
//if(segNum ==1 && segLth >=3 && segLth <=4)
{
//mid2 = 2*idx_s + segLth-1;
//printf("%.2f,%.2f\n",mid1, mid2);
//fflush(stdout);
//if(fabs(mid1-mid2) <=1){
breakFlag = true; //满足上述条件,通过直角点检测
dstP = p;
break;
//}
}
}
}
if(j==dstP.row +margin1)
break;
else
j = margin1>0? j+1:j-1;
}
if(breakFlag)
break;
if(i==dstP.col+margin)
break;
else
i = margin>0? i+1:i-1;
}
if(breakFlag)
return true;
else
return false;
}
/**
@brief
@param image 原始图像
@param softSize 检测模板大小,3:3X3,5:5X5
@param dstP 目标点
@param binaryThres局部二值化阈值
@param softSize 模板大小
@param segNum 检测到的段数
@param segLth 检测到的第一段长度
*/
void calcSegNumSegLth(uchar image[], uint auxSubIndex[], position &dstP, uchar binaryThres, uchar softSize,
uchar &segNum, uchar &segLth, uchar &idx_s)
{
uchar softLth =16, lth =0;
position p;
uchar *recoArr = NULL;
signed char *softP = coor5X5[0];
segNum = 0;
segLth = 0;
idx_s = 0;
if(3 == softSize){
softLth = 8;
softP = coor[0];
}else if(5 == softSize){
softLth = 16;
softP = coor5X5[0];
}
recoArr = (uchar *)malloc(softLth*2);
for(int k=0; k<softLth; k++){
//p.row = j + coor5X5[k][0];
//p.col = i + coor5X5[k][1];
p.row = dstP.row + *(softP+k*2);
p.col = dstP.col + *(softP+k*2+1);
//cout <<"dstP=("<<dstP.col<<","<<dstP.row<<") "<< "p=("<<p.col<<","<<p.row<<")"<<endl;
recoArr[k] = image[auxSubIndex[p.row]+p.col] < binaryThres; //0:黑 1:白
}
while(!recoArr[idx_s] && idx_s <softLth)
idx_s++;
if(idx_s>0){
for(int k=0; k <idx_s; k++)
recoArr[softLth+k] = recoArr[k];
}
lth = softLth+idx_s;
recoArr[lth] = 1;
for(int k=1; k <lth; k++)
{
if(recoArr[k-1] ==1 && recoArr[k]==0){
segNum++;
if(segNum ==1)
idx_s = k; //记录起始黑色点
else
break;
while(!recoArr[k]){
segLth++;
k++;
}
}
}
// if(5==softSize)
// {
// for(int k=0; k <lth; k++)
// {
// printf("%d ",recoArr[k]);
// fflush(stdout);
// }
// printf("soft=%dX%d, segNum=%d, segLth=%d, idx_s=%d\n\n",softSize, softSize, segNum, segLth, idx_s);
// fflush(stdout);
// }
}
/**
@breif 对一条直线上进行等间距点采样
@param s 直线起点
@param e 直线终点
@param sampNum 采样点数
@param sampGap 采样间隔
@param sps 采样点存储数组
*/
void samplePoints(position &s, position &e, const uchar sampNum, const uchar sampGap, position sps[])
{
float diff_X = e.col - s.col;
float diff_Y = e.row - s.row;
if(fabs(diff_X) >= fabs(diff_Y))
{
if(diff_X >0.0){
for(int i=0; i<sampNum; i++)
sps[i].col = s.col +sampGap*(i+2);
}else{
for(int i=0; i<sampNum; i++)
sps[i].col = s.col -sampGap*(i+2);
}
for(int i=0; i<sampNum; i++)
sps[i].row = s.row + (int)round((sps[i].col-s.col)/diff_X*diff_Y);
}else{
if(diff_Y>0.0){
for(int i=0; i<sampNum; i++)
sps[i].row = s.row +sampGap*(i+2);
}else{
for(int i=0; i<sampNum; i++)
sps[i].row = s.row -sampGap*(i+2);
}
for(int i=0; i<sampNum; i++)
sps[i].col = s.col + (int)round((sps[i].row - s.row)/diff_Y*diff_X);
}
}
/**
@brief 最小二乘法拟合线段
@param sps 有效的采样点
@param l 直线(结构体)
@param lparam 直线齐次坐标参数
*/
void LSnewAngle(position sps[], int spsLth, line_template &l, Hposition_f &lparam)
{
long A=0, B=0, C=0, D=0;
double k, b, tmp =0.0;
for(int i=0; i<spsLth; i++)
{
A += sps[i].col*sps[i].col;
B += sps[i].col;
C += sps[i].col*sps[i].row;
D += sps[i].row;
}
tmp=A*spsLth-B*B;
if(tmp){
k = (double)(C*spsLth-B*D)/tmp;
b = (double)(A*D-C*B)/tmp;
// printf("%f, %f\n", kk, b);
lparam.x = k;
lparam.y = -1;
lparam.scale = b;
l.dir = (float)atan(k)*180/3.141593;
// printf("%f\n",l.dir);
// fflush(stdout);
// printf("line new param %d, %d, %d\n",lparam.x, lparam.y, lparam.scale);
// fflush(stdout);
}else{
lparam.x = 1;
lparam.y = 0;
lparam.scale = -sps[0].col;
l.dir = 90.0;
}
}
///*@brief 根据检测到的freeman直线提取L并解码
// @param image 原始图像
// @param seg freeman线段数组
// @param segCnt freeman线段个数
// @param lthThres1 线段筛选阈值下限
// @param lthThres2 线段筛选阈值上限
//*/
//bool locateLeft(uchar *image, uint *auxSubIndex, line_template (&seg)[segNumLimit],int &segCnt, int lthThres1, int lthThres2, position &crossP, int &leftLineIdx, int &bottomLineIdx, float &theta)
//{
//// int i=0,j=0;
//// bool finishFlag=false;
//// for( ;i<segCnt;i++)
//// {
//// if(seg[i].pixNum >lthThres1 && seg[i].pixNum < lthThres2)
//// {
//// j=i+1;
//// for( ;j<segCnt;j++)
//// {
//// if(verify(image, auxSubIndex, seg, crossP, theta, leftLineIdx, bottomLineIdx, i, j, lthThres1, lthThres2)){
////#ifdef Debug
//// printf("line is %d and %d, cross point is (x,y)=(%d,%d)\n",i, j, crossP.col, crossP.row);
//// fflush(stdout);
////#endif
//// finishFlag = true;
//// return finishFlag;
//// }
//// }
//// }
//// }
//// return finishFlag;
// }
/*@brief 解码求相机位姿
@param image 原始图像
@param theta 角度
@param lth L边准确长度
@param crossP L边交点
@param POSE L解码的相机位姿
*/
//#define PLOT
bool decode(uchar *image, uint *auxSubIndex, float &theta, float <h, position &crossP, pose &POSE)
{
uchar grayTest[19];
memset(grayTest,0,19);
float scale = lth/20;
int grayThres=0;
//int tempCol=0, tempRow=0;
position tempPos={0,0};
uchar testSum=0;
for(int i=0;i<19;i++){
tempPos.col = crossP.col + locP[i].col*scale*cos(theta)-locP[i].row*scale*sin(theta);
tempPos.row = crossP.row + locP[i].col*scale*sin(theta)+locP[i].row*scale*cos(theta);
grayTest[i] = image[auxSubIndex[tempPos.row] + tempPos.col];
grayThres += grayTest[i];
#ifdef PLOT
drawPs[i] = tempPos;
printf("detect point (%d,%d)\n",locP[i].col, locP[i].row);
#endif
}
grayThres /=19;
#ifdef Debug
printf("gray threshold =%d\n",grayThres);
#endif
for(int i=1; i<19; i++,i++)
{
grayTest[i] = grayTest[i] >grayThres;
grayTest[i-1] = grayTest[i-1] >grayThres;
testSum +=grayTest[i]-grayTest[i-1];
#ifdef Debug
printf("%d, %d\n",grayTest[i-1], grayTest[i]);
//qDebug()<<grayTest[i-1]<<" "<<grayTest[i];
#endif
}
if(testSum <7)
return false;
uchar num[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
for(int i=0; i<8; i++)
{
tempPos.col = crossP.col + DatP[8*i].col*scale*cos(theta)-DatP[8*i].row*scale*sin(theta);
tempPos.row = crossP.row + DatP[8*i].col*scale*sin(theta)+DatP[8*i].row*scale*cos(theta);
num[i] |= (meanGray(image, auxSubIndex, tempPos) <grayThres) <<7;
#ifdef PLOT
drawDPs[8*i] = tempPos;
#endif
//grayDat[8*i] =image[preComput[tempRow]+tempCol] <grayThres;
tempPos.col = crossP.col + DatP[8*i+1].col*scale*cos(theta)-DatP[8*i+1].row*scale*sin(theta);
tempPos.row = crossP.row + DatP[8*i+1].col*scale*sin(theta)+DatP[8*i+1].row*scale*cos(theta);
num[i] |= (meanGray(image, auxSubIndex, tempPos) <grayThres) <<6;
#ifdef PLOT
drawDPs[8*i+1] = tempPos;
#endif
//grayDat[8*i+1] =image[preComput[tempRow]+tempCol] <grayThres;
tempPos.col = crossP.col + DatP[8*i+2].col*scale*cos(theta)-DatP[8*i+2].row*scale*sin(theta);
tempPos.row = crossP.row + DatP[8*i+2].col*scale*sin(theta)+DatP[8*i+2].row*scale*cos(theta);
num[i] |= (meanGray(image, auxSubIndex, tempPos) <grayThres) <<5;
#ifdef PLOT
drawDPs[8*i+2] = tempPos;
#endif
//grayDat[8*i+2] =image[preComput[tempRow]+tempCol] <grayThres;
tempPos.col = crossP.col + DatP[8*i+3].col*scale*cos(theta)-DatP[8*i+3].row*scale*sin(theta);
tempPos.row = crossP.row + DatP[8*i+3].col*scale*sin(theta)+DatP[8*i+3].row*scale*cos(theta);
num[i] |= (meanGray(image, auxSubIndex, tempPos) <grayThres) <<4;
#ifdef PLOT
drawDPs[8*i+3] = tempPos;
#endif
//grayDat[8*i+3] =image[preComput[tempRow]+tempCol] <grayThres;
tempPos.col = crossP.col + DatP[8*i+4].col*scale*cos(theta)-DatP[8*i+4].row*scale*sin(theta);
tempPos.row = crossP.row + DatP[8*i+4].col*scale*sin(theta)+DatP[8*i+4].row*scale*cos(theta);
num[i] |= (meanGray(image, auxSubIndex, tempPos) <grayThres) <<3;
#ifdef PLOT
drawDPs[8*i+4] = tempPos;
#endif
//grayDat[8*i+4] =image[preComput[tempRow]+tempCol] <grayThres;
tempPos.col = crossP.col + DatP[8*i+5].col*scale*cos(theta)-DatP[8*i+5].row*scale*sin(theta);
tempPos.row = crossP.row + DatP[8*i+5].col*scale*sin(theta)+DatP[8*i+5].row*scale*cos(theta);
num[i] |= (meanGray(image, auxSubIndex, tempPos) <grayThres) <<2;
#ifdef PLOT
drawDPs[8*i+5] = tempPos;
#endif
//grayDat[8*i+5] =image[preComput[tempRow]+tempCol] <grayThres;
tempPos.col = crossP.col + DatP[8*i+6].col*scale*cos(theta)-DatP[8*i+6].row*scale*sin(theta);
tempPos.row = crossP.row + DatP[8*i+6].col*scale*sin(theta)+DatP[8*i+6].row*scale*cos(theta);
num[i] |= (meanGray(image, auxSubIndex, tempPos) <grayThres)<<1;
#ifdef PLOT
drawDPs[8*i+6] = tempPos;
#endif
//grayDat[8*i+6] =image[preComput[tempRow]+tempCol] <grayThres;
tempPos.col = crossP.col + DatP[8*i+7].col*scale*cos(theta)-DatP[8*i+7].row*scale*sin(theta);
tempPos.row = crossP.row + DatP[8*i+7].col*scale*sin(theta)+DatP[8*i+7].row*scale*cos(theta);
num[i] |= (meanGray(image, auxSubIndex, tempPos) <grayThres);
#ifdef PLOT
drawDPs[8*i+7] = tempPos;
#endif
//grayDat[8*i+7] =image[preComput[tempRow]+tempCol] <grayThres;
//qDebug()<<grayDat[8*i]<<grayDat[8*i+1]<<grayDat[8*i+2]<<grayDat[8*i+3]<<grayDat[8*i+4]<<grayDat[8*i+5]<<grayDat[8*i+6]<<grayDat[8*i+7];
//qDebug()<<"num"<<i<<"="<<num[i]+0;
}
POSE.x = num[0]-130;
POSE.y = num[1]-130;
POSE.theta = theta;
return true;
}
/*@brief 计算p点周围8点像素的均值
@param image 原始图像
@param theta 角度
@param p 位置
*/
uchar meanGray(uchar *image, uint *auxSubIndex, position &p)
{
int sum=image[auxSubIndex[p.row]+p.col];
for(int i=0; i<8; i++){
sum += image[auxSubIndex[p.row+(int)coor[i][0]] + p.col+(int)coor[i][1]];
}
return sum/9;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。