最近一直为机器人做一个控制系统,需要同时搭载Tensorflow和海康网络摄像头,当然python是最好的开发工具,搭载tensorflow比较容易,但是搭载海康摄像头,一直找不到如何去做。后来又想到java,海康摄像头解决了,调用tensorflow训练模型又有很多的坑。暂时先用Qt做了,后面再想办法。只能用tenssorflow的ssd_mobilenet模型。opencv官方也没有更新其他的模型。
这是完成后的Qt控制系统界面。
关于海康摄像头的配置,完全看的海康的官方文档。
INCLUDEPATH+= D:\OpenCV\include\
D:\OpenCV\include\opencv\
D:\OpenCV\include\opencv2\
D:\CH-HCNetSDK_32\includes\
D:\CH-HCNetSDK_32\libs\
D:\CH-HCNetSDK_32\libs\HCNetSDKCom\
D:\CH-HCNetSDK_32\libs\ClientDemoDll\
LIBS += D:\OpenCV\x86\mingw\lib\libopencv_*.a\
D:\CH-HCNetSDK_32\libs\HCNetSDK.lib\
D:\CH-HCNetSDK_32\libs\PlayCtrl.lib\
D:\CH-HCNetSDK_32\libs\HCCore.lib\
void Robot::convexImage()
{
LONG lRealHandle=0;
NET_DVR_Init();
//设置连接时间与重连时间
NET_DVR_SetConnectTime(2000, 1);
NET_DVR_SetReconnect(10000, true);
if(bPlaying)
{
NET_DVR_StopRealPlay(lRealHandle);
NET_DVR_Logout_V30(lUserID);
lRealHandle=0;
lUserID=0;
bPlaying=false;
}
else
{
//注册设备
NET_DVR_DEVICEINFO_V30 struDeviceInfo;
//memset(&struDeviceInfo, 0, sizeof(NET_DVR_DEVICEINFO_V30));
lUserID = NET_DVR_Login_V30("10.20.15.96", 8000, "admin", "admin12345", &struDeviceInfo);
if(lUserID < 0)
{
qDebug()<<"login Err="<label_5->winId();
struPlayInfo.lChannel = 1; //预览通道
struPlayInfo.dwStreamType = 0; //主码流
struPlayInfo.dwLinkMode = 0; //TCP方式
lRealHandle = NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, NULL, NULL);
if (lRealHandle < 0)
{
QMessageBox::information(this, tr("NET_DVR_RealPlay error"), tr("SDK_LASTERROR=%1").arg(NET_DVR_GetLastError()));
NET_DVR_Logout_V30(lUserID);
ui->textEdit->append("高清摄像头显示异常!\t");
}
if(lRealHandle > 0)
{
bPlaying = true;
}
}
}
然后把海康给的dll和头文件都放在Qt中,防止出现打不开预览组件。
关于控制系统的变成,比较麻烦,
operateCommand.h
#define BGN_READ_MSG 0xff //起始符0xff
#define PROTOCOL_BASIC_SIZE 0x07 //protocal长度
#define MSG_EMPTY_MODEL 0x00 //默认设备号
#define MSG_EMPTY_MODEL_CMD 0x00 //默认设备命令
#define DATA_LEN 0x02 //数据长度
#define MSG_EMPTY_DATA 0x00 //空数据
enum enum_instruction
{
go=0x01,
back=0x02,
left_top=0x03,
right_top=0x04,
stop=0x05,
left_bottom=0x09,
right_bottom=0x0A,
deceleration=0x0B,
accelerate=0x0C,
};
enum enum_mode
{
zero=0x00,//指令
one=0x01,//环境温度
two=0x02,//红外测温
three=0x03,//接受
four=0x04,//错误
five=0x05,//初始化
six=0x06,//浓度
seven=0x07,//环境湿度
};
struct Settings
{
enum_instruction instructing;
enum_mode mode;
};
robot.h
#ifndef ROBOT_H
#define ROBOT_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
class QTcpSocket;
namespace Ui {
class Robot;
}
class Robot : public QMainWindow
{
Q_OBJECT
public:
explicit Robot(QWidget *parent = 0);
~Robot();
void execCmd(QByteArray buff); //解析读取的指令
signals:
void signalReceiveData(QByteArray buff); //接受数据
void signalInfraredTemperature(quint16,quint16); //红外温度
void signalEnvironmentTemperature(quint16,quint16); //环境温度
void signalEnvironmentHumidity(quint16,quint16); //湿度
void signalEnvironmentGasCon(quint16,quint16); //气体浓度
//电机控制
void signalMachineryControl(quint16 ,quint16 );
private slots:
void on_open_pushButton_clicked();
void on_close_pushButton_clicked();
void on_forward_pushButton_clicked();
void convexImage();
void slotReadData(); //读取数据槽函数
//接收电机信息,向下位机发送
void slotReceiveMachineryValue(quint16 ,quint16);
void on_back_pushButton_clicked();
void on_stop_pushButton_clicked();
private:
Ui::Robot *ui;
QTcpSocket *tcpSocket;
QString currentForture;
quint16 blockSuze;
QSerialPort *my_serialport;
QImage img;
QTimer *time_clock;
private:
void senddata();
void packSendData(quint16 drive, quint16 drive_cmd,
quint16 data_len, quint16 data1,quint16 data2); //发送整包数据
void initData(); //清空数据
void initConnect(); //连接信号与槽
void execData(); //
void exec_InfTemData(QByteArray buff); //红外测温
void exec_TemData(QByteArray buff); //环境温度temperature
void exec_HumData(QByteArray buff); //环境湿度humidity
void exec_GasData(QByteArray buff); //可燃气气体浓度Gas
//控制电机
void sendMachineryCmd(quint16 data1,quint16 data2);
void sendForwardCmd(quint16 drive,const QString &); //前进指令
void sendBackCmd(quint16 drive,const QString &); //后退指令
void sendForwardLeftCmd(quint16 drive,const QString &); //左前行走
void sendForwardRightCmd(quint16 drive,const QString &); //右前行走
void sendBackLeftCmd(quint16 drive,const QString &); //左退行走
void sendBackRightCmd(quint16 drive,const QString &); //右退行走
void sendAccelerateCmd(quint16 drive,const QString &); //加速行走
void sendDeaccelerateCmd(quint16 drive,const QString &); //减速行走
void sendStopCmd(quint16 drive,const QString &); //停止
private:
quint16 m_sendBegin; //起始标志
quint16 m_potocolLen; //信息长度
quint16 m_device; //设备名
quint16 m_deviceCmd; //设备命令
quint16 m_dataLen; //数据长度
quint16 m_data_1; //数据1
quint16 m_data_2; //数据2
quint16 checkcode; //校验位
quint16 getProtocolLen(); //获取信息长度
quint16 getDevice(); //获取设备名
quint16 getDeviceCmd(); //设备使能
quint16 getDataLen(); //数据长度
quint16 getData1(); //获取数据1
quint16 getData2(); //获取数据2
quint16 getCheckCode(); //获取校验码
};
#endif // ROBOT_H
StrToHex.h
#ifndef STRTOHEX_H
#define STRTOHEX_H
#include
#include
#include
#include "robot.h"
class STRTOHEX:public QObject
{
public:
//16进制字符串转字符数组
static QByteArray HexstrToByteArray(QString str)
{
QByteArray senddata;
int hexdata,lowhexdata;
int hexdatalen=0;
int len=str.length();
senddata.resize(len/2);
char lstr,hstr;
for(int i=0;i=len)
break;
lstr=str[i].toLatin1();
hexdata=ConvertHexChar(hstr);
lowhexdata=ConvertHexChar(lstr);
if((hexdata==16)||(lowhexdata==16))
break;
else
hexdata=hexdata*16+lowhexdata;
i++;
senddata[hexdatalen]=(char)hexdata;
hexdatalen++;
}
senddata.resize(hexdatalen);
return senddata;
}
//转字符型
static char ConvertHexChar(char ch)
{
if((ch>='0')&&(ch<='9'))
return ch-0x30;
else if((ch>='A')&&(ch<='F'))
return ch-'A'+10;
else if((ch>='a')&&(ch<='f'))
return ch-'a'+10;
else return (-1);
}
//字节数组转16进制字符串
static QString ByteArrayToHexStr(QByteArray data)
{
QString temp=" ";
QString hex=data.toHex();
for(int i=0;i127)
{
temp=data+256;
}
else
{
temp=data;
}
return temp;
}
//延时
static void Sleep(int sec)
{
QTime dieTime = QTime::currentTime().addMSecs(sec);
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
};
#endif // STRTOHEX_H
//发送数据
void Robot::senddata()
{
QByteArray str;
str.append(m_sendBegin);
str.append(getProtocolLen());
str.append(getDevice());
str.append(getDeviceCmd());
str.append(getDataLen());
str.append(getData1());
str.append(getData2());
//str.append(getCheckCode());
checkcode=STRTOHEX::GetCheckCode(str,7);
str.append(checkcode);
QString outData;
outData=STRTOHEX::ByteArrayToHexStr(str);
ui->textEdit->append("开始发送数据\t");
ui->textEdit->append(outData);
ui->textEdit->append("\t");
tcpSocket->write(str);
STRTOHEX::Sleep(50);
tcpSocket->write(str);
}