[]@
TOC
前言
本文主要实现使用Qt做软甲界面,opencv做魔方识别,本软件主要是配合机械手进行通信完成魔方的识别
机器人:ABB双臂机器人
效果视频
本软件效果如下:
c++/opencv实现魔方还原
工程目录如下:
- CtuLib:此工程包含了多个算法,包括软件加密,opencv图像处理算法,魔方还原算法等
一、算法库的构建:CtuLib.dll
本文收集了大量资料并且根据根据个人经验,实现了一个基于C++写的算法库,并且本算法库是多个命名空间,实现多个算法
CtuLib.h内容如下:
1.基于opencv实现的算法
namespace CtuLibLink
{
CTULIB_API bool read_image(cv::Mat* img, std::string fileName,bool nchannels=false);
CTULIB_API bool write_image(cv::Mat* img,std::string SavePath);
CTULIB_API bool ConnectedCamera(int Type=0,int Num=0);
CTULIB_API bool DisConnectedCamera();
CTULIB_API bool CameraIsConnected();
CTULIB_API bool GetOnceImage(cv::Mat* img);
CTULIB_API bool DrawModelROI(cv::Mat* img, cv::Mat* model,cv::Rect* rect,int min_width=500);
CTULIB_API bool DrawPoint(cv::Mat* img,cv::Rect rect,cv::Point* point,int min_width=500);
CTULIB_API bool DrawSearchROI(cv::Mat* img, cv::Mat* searchROI,cv::Rect* rect,int min_width=500);
CTULIB_API bool FindModel1(cv::Mat img,cv::Mat model,cv::Mat* dst,cv::Point* p);
CTULIB_API bool SetCalib(double ImageX[3],double Image_Y[3],double Robot_X[3],double Robot_Y[3]);
CTULIB_API bool GetP(double ImageX,double Image_Y,double* Robot_X,double* Robot_Y);
CTULIB_API void Rotate_Angle(cv::Mat &src,cv::Mat &dst,float angle);
}
2.魔方还原算法
namespace MagicCubeLink
{
CTULIB_API std::vector<std::string> GetCubeFunc(int data[6][9],int countNum=100000);
CTULIB_API std::vector<std::string> GetCubeFlipFunc(std::vector<std::string> data);
CTULIB_API std::vector<std::string> GetCubeData(int data[6][9]);
CTULIB_API cv::Scalar getAvgBGR(cv::Mat img);
CTULIB_API std::string isDigitStr(std::string src);
}
namespace MagicCubeFastLink
{
CTULIB_API std::vector<std::string> GetCubeFunc(int data[6][9]);
}
3.软加密方式
namespace PermissionLink
{
CTULIB_API bool GetData(char* uuid,int check);
CTULIB_API bool AddUser(char* recv,char* Project,char* ID);
CTULIB_API bool CheckUser(char* recv,char* Project,char* ID);
CTULIB_API bool DeleteUser(char* recv,char* Project,char* ID);
CTULIB_API bool FindAllUser(char* recv,char* Project);
CTULIB_API bool GetMinWen(char* mingwen,char* miwen);
CTULIB_API bool Registration(char* writemes,char* fileName);
CTULIB_API bool CheckRegistration(char* fileName);
}
4.软件狗加密方式:ET99
namespace MircoDogLink
{
CTULIB_API void SoftWareCheck(std::string KeyData_ID,int length,Fun pCallback);
CTULIB_API void SoftWareCheck_Once(std::string KeyData_ID,int length,bool* res);
CTULIB_API int WriteDog(std::string KeyData_ID,std::string miwen,bool* res);
CTULIB_API void GetDogID(DWORD* data1,DWORD* data2,bool* res);
}
namespace ET99DLLLink
{
CTULIB_API bool SoftWareCheck(Fun pCallback);
CTULIB_API void SoftWareCheck_Once(bool* res);
}
二、魔方还原
界面主要看视频即可
1.工程目录如下:
2.重要代码
1.2D
//刷新平面2D界面图
void MagicCube::Auto_Ref_2D()
{
for(int i=0;i<6;i++)
{
for(int j=0;j<9;j++)
{
ShowLab[i][j]->setStyleSheet(SetCircleMes(Magic_Data.Magic_Data[i][j]));
ShowLab[i][j]->setText(QString::number(Magic_Data.Magic_Data[i][j]));
}
}
}
如图:
2.3D
3D效果图主要是用opengl方式进行绘制,对27个方格进行绘制
void Model_3D_Cube::upDataColor(int data[6][9])
{
//0->前 1->后 2->下 3->上 4->右 5->左
//1
cubeWidget->rotatecube[0]->color[0]=getColor(data[FORWARD_COLOR][6]);
cubeWidget->rotatecube[0]->color[1]=getColor(0);
cubeWidget->rotatecube[0]->color[2]=getColor(data[DOWN_COLOR][0]);
cubeWidget->rotatecube[0]->color[3]=getColor(0);
cubeWidget->rotatecube[0]->color[4]=getColor(0);
cubeWidget->rotatecube[0]->color[5]=getColor(data[LEFT_COLOR][8]);
//2
cubeWidget->rotatecube[1]->color[0]=getColor(data[FORWARD_COLOR][7]);
cubeWidget->rotatecube[1]->color[1]=getColor(0);
cubeWidget->rotatecube[1]->color[2]=getColor(data[DOWN_COLOR][1]);
cubeWidget->rotatecube[1]->color[3]=getColor(0);
cubeWidget->rotatecube[1]->color[4]=getColor(0);
cubeWidget->rotatecube[1]->color[5]=getColor(0);
//3
cubeWidget->rotatecube[2]->color[0]=getColor(data[FORWARD_COLOR][8]);
cubeWidget->rotatecube[2]->color[1]=getColor(0);
cubeWidget->rotatecube[2]->color[2]=getColor(data[DOWN_COLOR][2]);
cubeWidget->rotatecube[2]->color[3]=getColor(0);
cubeWidget->rotatecube[2]->color[4]=getColor(data[RIGHT_COLOR][6]);
cubeWidget->rotatecube[2]->color[5]=getColor(0);
//4
cubeWidget->rotatecube[3]->color[0]=getColor(data[FORWARD_COLOR][3]);
cubeWidget->rotatecube[3]->color[1]=getColor(0);
cubeWidget->rotatecube[3]->color[2]=getColor(0);
cubeWidget->rotatecube[3]->color[3]=getColor(0);
cubeWidget->rotatecube[3]->color[4]=getColor(0);
cubeWidget->rotatecube[3]->color[5]=getColor(data[LEFT_COLOR][5]);
//5
cubeWidget->rotatecube[4]->color[0]=getColor(data[FORWARD_COLOR][4]);
cubeWidget->rotatecube[4]->color[1]=getColor(0);
cubeWidget->rotatecube[4]->color[2]=getColor(0);
cubeWidget->rotatecube[4]->color[3]=getColor(0);
cubeWidget->rotatecube[4]->color[4]=getColor(0);
cubeWidget->rotatecube[4]->color[5]=getColor(0);
//6
cubeWidget->rotatecube[5]->color[0]=getColor(data[FORWARD_COLOR][5]);
cubeWidget->rotatecube[5]->color[1]=getColor(0);
cubeWidget->rotatecube[5]->color[2]=getColor(0);
cubeWidget->rotatecube[5]->color[3]=getColor(0);
cubeWidget->rotatecube[5]->color[4]=getColor(data[RIGHT_COLOR][3]);
cubeWidget->rotatecube[5]->color[5]=getColor(0);
//7
cubeWidget->rotatecube[6]->color[0]=getColor(data[FORWARD_COLOR][0]);
cubeWidget->rotatecube[6]->color[1]=getColor(0);
cubeWidget->rotatecube[6]->color[2]=getColor(0);
cubeWidget->rotatecube[6]->color[3]=getColor(data[UP_COLOR][6]);
cubeWidget->rotatecube[6]->color[4]=getColor(0);
cubeWidget->rotatecube[6]->color[5]=getColor(data[LEFT_COLOR][2]);
//8
cubeWidget->rotatecube[7]->color[0]=getColor(data[FORWARD_COLOR][1]);
cubeWidget->rotatecube[7]->color[1]=getColor(0);
cubeWidget->rotatecube[7]->color[2]=getColor(0);
cubeWidget->rotatecube[7]->color[3]=getColor(data[UP_COLOR][7]);
cubeWidget->rotatecube[7]->color[4]=getColor(0);
cubeWidget->rotatecube[7]->color[5]=getColor(0);
//9
cubeWidget->rotatecube[8]->color[0]=getColor(data[FORWARD_COLOR][2]);
cubeWidget->rotatecube[8]->color[1]=getColor(0);
cubeWidget->rotatecube[8]->color[2]=getColor(0);
cubeWidget->rotatecube[8]->color[3]=getColor(data[UP_COLOR][8]);
cubeWidget->rotatecube[8]->color[4]=getColor(data[RIGHT_COLOR][0]);
cubeWidget->rotatecube[8]->color[5]=getColor(0);
//10
cubeWidget->othercube[0]->color[0]=getColor(0);
cubeWidget->othercube[0]->color[1]=getColor(0);
cubeWidget->othercube[0]->color[2]=getColor(data[DOWN_COLOR][3]);
cubeWidget->othercube[0]->color[3]=getColor(0);
cubeWidget->othercube[0]->color[4]=getColor(0);
cubeWidget->othercube[0]->color[5]=getColor(data[LEFT_COLOR][7]);
//11
cubeWidget->othercube[1]->color[0]=getColor(0);
cubeWidget->othercube[1]->color[1]=getColor(0);
cubeWidget->othercube[1]->color[2]=getColor(data[DOWN_COLOR][4]);
cubeWidget->othercube[1]->color[3]=getColor(0);
cubeWidget->othercube[1]->color[4]=getColor(0);
cubeWidget->othercube[1]->color[5]=getColor(0);
//12
cubeWidget->othercube[2]->color[0]=getColor(0);
cubeWidget->othercube[2]->color[1]=getColor(0);
cubeWidget->othercube[2]->color[2]=getColor(data[DOWN_COLOR][5]);
cubeWidget->othercube[2]->color[3]=getColor(0);
cubeWidget->othercube[2]->color[4]=getColor(data[RIGHT_COLOR][7]);
cubeWidget->othercube[2]->color[5]=getColor(0);
//13
cubeWidget->othercube[3]->color[0]=getColor(0);
cubeWidget->othercube[3]->color[1]=getColor(0);
cubeWidget->othercube[3]->color[2]=getColor(0);
cubeWidget->othercube[3]->color[3]=getColor(0);
cubeWidget->othercube[3]->color[4]=getColor(0);
cubeWidget->othercube[3]->color[5]=getColor(data[LEFT_COLOR][4]);
//14
cubeWidget->othercube[4]->color[0]=getColor(0);
cubeWidget->othercube[4]->color[1]=getColor(0);
cubeWidget->othercube[4]->color[2]=getColor(0);
cubeWidget->othercube[4]->color[3]=getColor(0);
cubeWidget->othercube[4]->color[4]=getColor(0);
cubeWidget->othercube[4]->color[5]=getColor(0);
//15
cubeWidget->othercube[5]->color[0]=getColor(0);
cubeWidget->othercube[5]->color[1]=getColor(0);
cubeWidget->othercube[5]->color[2]=getColor(0);
cubeWidget->othercube[5]->color[3]=getColor(0);
cubeWidget->othercube[5]->color[4]=getColor(data[RIGHT_COLOR][4]);
cubeWidget->othercube[5]->color[5]=getColor(0);
//16
cubeWidget->othercube[6]->color[0]=getColor(0);
cubeWidget->othercube[6]->color[1]=getColor(0);
cubeWidget->othercube[6]->color[2]=getColor(0);
cubeWidget->othercube[6]->color[3]=getColor(data[UP_COLOR][3]);
cubeWidget->othercube[6]->color[4]=getColor(0);
cubeWidget->othercube[6]->color[5]=getColor(data[LEFT_COLOR][1]);
//17
cubeWidget->othercube[7]->color[0]=getColor(0);
cubeWidget->othercube[7]->color[1]=getColor(0);
cubeWidget->othercube[7]->color[2]=getColor(0);
cubeWidget->othercube[7]->color[3]=getColor(data[UP_COLOR][4]);
cubeWidget->othercube[7]->color[4]=getColor(0);
cubeWidget->othercube[7]->color[5]=getColor(0);
//18
cubeWidget->othercube[8]->color[0]=getColor(0);
cubeWidget->othercube[8]->color[1]=getColor(0);
cubeWidget->othercube[8]->color[2]=getColor(0);
cubeWidget->othercube[8]->color[3]=getColor(data[UP_COLOR][5]);
cubeWidget->othercube[8]->color[4]=getColor(data[RIGHT_COLOR][1]);
cubeWidget->othercube[8]->color[5]=getColor(0);
//19
cubeWidget->othercube[9]->color[0]=getColor(0);
cubeWidget->othercube[9]->color[1]=getColor(data[BACK_COLOR][8]);
cubeWidget->othercube[9]->color[2]=getColor(data[DOWN_COLOR][6]);
cubeWidget->othercube[9]->color[3]=getColor(0);
cubeWidget->othercube[9]->color[4]=getColor(0);
cubeWidget->othercube[9]->color[5]=getColor(data[LEFT_COLOR][6]);
//20
cubeWidget->othercube[10]->color[0]=getColor(0);
cubeWidget->othercube[10]->color[1]=getColor(data[BACK_COLOR][7]);
cubeWidget->othercube[10]->color[2]=getColor(data[DOWN_COLOR][7]);
cubeWidget->othercube[10]->color[3]=getColor(0);
cubeWidget->othercube[10]->color[4]=getColor(0);
cubeWidget->othercube[10]->color[5]=getColor(0);
//21
cubeWidget->othercube[11]->color[0]=getColor(0);
cubeWidget->othercube[11]->color[1]=getColor(data[BACK_COLOR][6]);
cubeWidget->othercube[11]->color[2]=getColor(data[DOWN_COLOR][8]);
cubeWidget->othercube[11]->color[3]=getColor(0);
cubeWidget->othercube[11]->color[4]=getColor(data[RIGHT_COLOR][8]);
cubeWidget->othercube[11]->color[5]=getColor(0);
//22
cubeWidget->othercube[12]->color[0]=getColor(0);
cubeWidget->othercube[12]->color[1]=getColor(data[BACK_COLOR][5]);
cubeWidget->othercube[12]->color[2]=getColor(0);
cubeWidget->othercube[12]->color[3]=getColor(0);
cubeWidget->othercube[12]->color[4]=getColor(0);
cubeWidget->othercube[12]->color[5]=getColor(data[LEFT_COLOR][3]);
//23
cubeWidget->othercube[13]->color[0]=getColor(0);
cubeWidget->othercube[13]->color[1]=getColor(data[BACK_COLOR][4]);
cubeWidget->othercube[13]->color[2]=getColor(0);
cubeWidget->othercube[13]->color[3]=getColor(0);
cubeWidget->othercube[13]->color[4]=getColor(0);
cubeWidget->othercube[13]->color[5]=getColor(0);
//24
cubeWidget->othercube[14]->color[0]=getColor(0);
cubeWidget->othercube[14]->color[1]=getColor(data[BACK_COLOR][3]);
cubeWidget->othercube[14]->color[2]=getColor(0);
cubeWidget->othercube[14]->color[3]=getColor(0);
cubeWidget->othercube[14]->color[4]=getColor(data[RIGHT_COLOR][5]);
cubeWidget->othercube[14]->color[5]=getColor(0);
//25
cubeWidget->othercube[15]->color[0]=getColor(0);
cubeWidget->othercube[15]->color[1]=getColor(data[BACK_COLOR][2]);
cubeWidget->othercube[15]->color[2]=getColor(0);
cubeWidget->othercube[15]->color[3]=getColor(data[UP_COLOR][0]);
cubeWidget->othercube[15]->color[4]=getColor(0);
cubeWidget->othercube[15]->color[5]=getColor(data[LEFT_COLOR][0]);
//26
cubeWidget->othercube[16]->color[0]=getColor(0);
cubeWidget->othercube[16]->color[1]=getColor(data[BACK_COLOR][1]);
cubeWidget->othercube[16]->color[2]=getColor(0);
cubeWidget->othercube[16]->color[3]=getColor(data[UP_COLOR][1]);
cubeWidget->othercube[16]->color[4]=getColor(0);
cubeWidget->othercube[16]->color[5]=getColor(0);
//27
cubeWidget->othercube[17]->color[0]=getColor(0);
cubeWidget->othercube[17]->color[1]=getColor(data[BACK_COLOR][0]);
cubeWidget->othercube[17]->color[2]=getColor(0);
cubeWidget->othercube[17]->color[3]=getColor(data[UP_COLOR][2]);
cubeWidget->othercube[17]->color[4]=getColor(data[RIGHT_COLOR][2]);
cubeWidget->othercube[17]->color[5]=getColor(0);
}
如图:
3.生成队列
void MagicCube::on_pushButton_CreateData_clicked()
{
ui.TabWidget_ODNGMes->clear();
ui.TabWidget_ODNGMes->setRowCount(0);
QStringList header;
header<<QStringLiteral("ID")<<QStringLiteral("Data");
ui.TabWidget_ODNGMes->setHorizontalHeaderLabels(header);
for (int i=0;i<ui.TabWidget_ODNGMes->columnCount();i++)
ui.TabWidget_ODNGMes->setColumnWidth(i,15);
for(int i=0;i<6;i++)
{
if(Magic_Data.Magic_Flag[i]==false)
{
ShowMessageToLog(QStringLiteral("识别颜色不全"));
return;
}
}
int temp_Num[6]={0,0,0,0,0,0};
for(int i=0;i<6;i++)
{
for(int j=0;j<9;j++)
{
temp_Num[Magic_Data.Magic_Data[i][j]-1]++;
}
}
for(int i=0;i<6;i++)
{
if(temp_Num[i]!=9)
{
ShowMessageToLog(QStringLiteral("颜色数据错误"));
return;
}
}
Magic_Queue.clear();
if(Function_Fast == 1)
Magic_Queue = MagicCubeFastLink::GetCubeFunc(Magic_Data.Magic_Data);
else
Magic_Queue = MagicCubeLink::GetCubeFunc(Magic_Data.Magic_Data);
if(DataModel == "1")
Magic_Queue = MagicCubeLink::GetCubeFlipFunc(Magic_Queue);
if(Magic_Queue.size()>0)
{
ShowMessageToLog(QStringLiteral("队列形成!"));
for(int i=0;i<Magic_Queue.size();i++)
{
try{
int Num = ui.TabWidget_ODNGMes->rowCount();
ui.TabWidget_ODNGMes->insertRow(Num);
ui.TabWidget_ODNGMes->setItem(Num,0,new QTableWidgetItem(QString::number(Num+1)));
ui.TabWidget_ODNGMes->setItem(Num,1,new QTableWidgetItem(QString::fromStdString(Magic_Queue.at(Num))));
QCoreApplication::processEvents(QEventLoop::AllEvents, 5);
}catch(...){}
}
}
else
{
ShowMessageToLog(QStringLiteral("队列形成失败!"));
}
}
三、机器人协议
DefaultSetting.ini
IP配置文件
视觉(计算机)IP:192.168.0.200,255.255.255.0;
机器人IP:192.168.0.10,255.255.255.0
Angle=180
1、双击“MagiCube.exe”,点击相机,点击连接相机,ID为0,代表外部相机(###建议:重启软件时自动连接上次所选相机)
2、点击相机,开始预览
3、颜色设置,绘制搜索区域,(###建议:搜索区域重启软件应保留上次设置)
4、参数设置,点击区域划分,修改,修改颜色区域范围,保存(参数文件:color.dat)
5、测试颜色,执行识别
6、点击运行(###建议:新增功能,点击运行后,窗口按钮不可再操作)
7、颜色识别(机器人触发,颜色识别程序)(###建议:机器人与视觉通讯链接已建立,机器人发:Hello Vision,视觉发:Hello Robot)
8、点击操作,数据生成(提示队列形成)(###建议:机器人发:GetData,视觉发:DataOK(队列形成),DataNG(队列形成失败)
9、点击操作,点击运行(视觉发:S,Start 返回:R,Start,OK)(###建议:机器人发:Run,视觉发:Run OK )
机器人连接成功:
视觉发:S,00
机器人清空数据队列:
机器人发:R,Clear,F 返回:S,Clear,F,OK
机器人发:R,Clear,B 返回:S,Clear,B,OK
机器人发:R,Clear,L 返回:S,Clear,L,OK
机器人发:R,Clear,R 返回:S,Clear,R,OK
机器人发:R,Clear,U 返回:S,Clear,U,OK
机器人发:R,Clear,D 返回:S,Clear,D,OK
机器人发:R,Clear,A 返回:S,Clear,A,OK
颜色识别程序:
机器人发:R,F 返回:S,F,OK (S,F,NG) (前) 21 r21Move_RF_L
机器人发:R,B 返回:S,B,OK (S,B,NG) (后) 22 r22Move_RB_L
机器人发:R,L 返回:S,L,OK (S,L,NG) (左)23 r23Move_RL_L
机器人发:R,R 返回:S,R,OK (S,R,NG) (右)24 r24Move_RR_L
机器人发:R,U 返回:S,U,OK(S,U,NG) (上)25 r25Move_RU_L
机器人发:R,D 返回:S,D,OK(S,D,NG) (下)26 r26Move_RD_L
颜色识别完,机器人要求生成队列
机器人发:R,Cali 返回:S,Cali,OK (S,Cali,NG)
机器人要求开始转魔方:
机器人发:R,Start 视觉返回:S,Start,OK(S,Start,NG) 机器人返回:R,Start,OK
程序运行:(###建议:视觉发两步指令:第1步;第2步(第2步;第3步);S,F1,1;S,F1,1;最后1步后跟S,End0)每组数据6个字符,以“;”分隔
前面F(左手)###
视觉发:S,F1,1 机器人旋转完:R,F1,1,OK(顺时针90) 31 r31S_F1_1_L
视觉发:S,F1,0 机器人旋转完:R,F1,0,OK(逆时针90) 32 r32S_F1_0_L
视觉发:S,F2,1 机器人旋转完:R,F2,1,OK(顺时针180) 33 r33S_F2_1_L
后面B(右手)
视觉发:S,B1,1 机器人旋转完:R,B1,1,OK(顺时针90) 41 r41S_B1_1_R
视觉发:S,B1,0 机器人旋转完:R,B1,0,OK(逆时针90) 42 r42S_B1_0_R
视觉发:S,B2,1 机器人旋转完:R,B2,1,OK(顺时针180) 43 r43S_B2_1_R
左面L(左手)###
视觉发:S,L1,1 机器人旋转完:R,L1,1,OK(顺时针90) 51 r51S_L1_1_L
视觉发:S,L1,0 机器人旋转完:R,L1,0,OK(逆时针90) 52 r52S_L1_0_L
视觉发:S,L2,1 机器人旋转完:R,L2,1,OK(顺时针180) 53 r53S_L2_1_L
右面R(右手)
视觉发:S,R1,1 机器人旋转完:R,R1,1,OK(顺时针90) 61 r61S_R1_1_R
视觉发:S,R1,0 机器人旋转完:R,R1,0,OK(逆时针90) 62 r62S_R1_0_R
视觉发:S,R2,1 机器人旋转完:R,R2,1,OK(顺时针180) 63 r63S_R2_1_R
上面U(左手)###
视觉发:S,U1,1 机器人旋转完:R,U1,1,OK(顺时针90) 71 r71S_U1_1_L
视觉发:S,U1,0 机器人旋转完:R,U1,0,OK(逆时针90) 72 r72S_U1_0_L
视觉发:S,U2,1 机器人旋转完:R,U2,1,OK(顺时针180) 73 r73S_U2_1_L
下面D(右手)
视觉发:S,D1,1 机器人旋转完:R,D1,1,OK(顺时针90) 81 r81S_D1_1_R
视觉发:S,D1,0 机器人旋转完:R,D1,0,OK(逆时针90) 82 r82S_D1_0_R
视觉发:S,D2,1 机器人旋转完:R,D2,1,OK(顺时针180) 83 r83S_D2_1_R
动作完成(代表无指令):
视觉发:S,End 返回:R,End,OK
总结
感兴趣及对代码感兴趣可私聊
版权声明:本文为ctu_sue原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。