之前帮一个算法朋友弄的 ONVIF PTZ控制海康云台相机代码在无人车上的应用.

主要是鉴权没弄过,折腾onvif的人肯定会碰到,所以特别记录一下.

开始本来是在X64的WIN32或ubuntu工控机平台弄海康摄像头控制的,因为有SDK的直接支持.

结果无人车主控选的是NVIDIA XAIVER arm下控制云台,这就想起了用ONVIF了.

ONVIF无非就是用gsoap+rtsp来折腾的 就把gsoap库先下载和onvif官方下载对应的文件wsdl接口.如果是搞过webservice的活应该有所了解, gsoap 我不多说 百度一下应该好多讲的只管下载.

版本没有太大的要求, 下面文件有些我可能删除了. 我保留主要文件 .

onvif标准接口也是下载 一堆wsdl文件  PTZ在下面

主要作用类的封装:

class OnvifSDK
{
public:std::string MediaAddr;std::string PTZAddr;
public:static struct soap* NewSoap(const char* ip);OnvifSDK(struct soap* soap_, const char* username, const char* password);virtual ~OnvifSDK();bool GetDeviceInfo(char* url);bool GetCapabilities(char* url);bool GetProfiles();std::string GetUri(enum tt__TransportProtocol transtype);bool GetStstus(float* pvalue, float* tvalue, float* zvalue);//连续控制void ControlPTZ(int control, bool control_type, int speed);//绝对控制void SetPTZ(float pvalue, float tvalue, float zvalue);//相对控制void SetMoveStep(ptz_common commond, float move_step);
protected:
#ifdef WITH_OPENSSL
#elsevoid calc_nonce(struct soap* soap, char nonce[SOAP_WSSE_NONCELEN]);struct _wsse__Security* soap_wsse_add_Security(struct soap* soap);int soap_wsse_add_UsernameTokenText(struct soap* soap, const char* id, const char* username, const char* password);int soap_wsse_add_UsernameTokenDigest(struct soap* soap, const char* id, const char* username, const char* password);void calc_digest(struct soap* soap, const char* created,const char* nonce, int noncelen, const char* password, char hash[SOAP_SMD_SHA1_SIZE]);void TokenTimestmap(struct soap* pSoap, time_t lifetime = TOKEN_TIMESTAMP);int soap_wsse_add_Timestamp(struct soap* soap, const char* id, time_t lifetime);
#endif
private:std::string UserName;std::string PassWord;std::string Band;enum xsd__boolean TrueFlag;struct tt__PTZSpeed PTZSpeed;struct tt__Vector2D PTZVectorPT;struct tt__Vector1D PTZVectorZ;struct tt__PTZVector VectorABSPTZ;struct soap* soap;struct _tds__GetCapabilities capa_req;struct _tds__GetCapabilitiesResponse capa_resp;struct _trt__GetProfiles trt__GetProfiles;struct _trt__GetProfilesResponse trt__GetProfilesResponse;struct _trt__GetStreamUri trt__GetStreamUri;struct _trt__GetStreamUriResponse trt__GetStreamUriResponse;struct _tptz__GetStatus tptz__GetStatus;struct _tptz__GetStatusResponse tptz__GetStatusResponse;struct _tptz__ContinuousMove tptz__ContinuousMove;struct _tptz__ContinuousMoveResponse tptz__ContinuousMoveResponse;struct _tptz__Stop tptz__Stop;struct _tptz__StopResponse tptz__StopResponse;struct _tds__GetDeviceInformation tds__GetDeviceInformation;struct _tds__GetDeviceInformationResponse tds__GetDeviceInformationResponse;struct _tptz__AbsoluteMove tptz__AbsoluteMove;struct _tptz__AbsoluteMoveResponse tptz__AbsoluteMoveResponse;struct _tptz__RelativeMove tptz__RelativeMove;struct _tptz__RelativeMoveResponse tptz__RelativeMoveResponse;
};

实现部分(ptz控制方法):

bool OnvifSDK::GetDeviceInfo(char* url)
{soap_wsse_add_UsernameTokenDigest(soap, "", UserName.c_str(), PassWord.c_str());int ret = soap_call___tds__GetDeviceInformation(soap, url, NULL, &tds__GetDeviceInformation, &tds__GetDeviceInformationResponse);if (ret != SOAP_OK)return false;if (soap->error)return false;else{Band = std::string(tds__GetDeviceInformationResponse.Manufacturer);return true;}
}bool OnvifSDK::GetCapabilities(char* url)
{capa_req.__sizeCategory = 1;capa_req.Category =  (enum tt__CapabilityCategory*)malloc(sizeof(enum tt__CapabilityCategory));enum tt__CapabilityCategory temp_category = tt__CapabilityCategory__All;capa_req.Category = &temp_category;capa_resp.Capabilities =  (struct tt__Capabilities*)malloc(sizeof(struct tt__Capabilities)) ;soap_wsse_add_UsernameTokenDigest(soap, "", UserName.c_str(), PassWord.c_str());int result = soap_call___tds__GetCapabilities(soap, url, NULL, &capa_req, &capa_resp);if (soap->error){return false;}else{if (capa_resp.Capabilities == NULL){printf(" GetCapabilities  failed!  result=%d \n", result);return false;}else{printf(" Media->XAddr=%s \n", capa_resp.Capabilities->Media->XAddr);printf(" Media->PTZ=%s \n", capa_resp.Capabilities->PTZ->XAddr);return true;}}
}bool OnvifSDK::GetProfiles()
{soap_wsse_add_UsernameTokenDigest(soap, "", UserName.c_str(), PassWord.c_str());if (soap_call___trt__GetProfiles(soap, capa_resp.Capabilities->Media->XAddr, NULL, &trt__GetProfiles, &trt__GetProfilesResponse) == -1){return false;}else{if (trt__GetProfilesResponse.Profiles != NULL){if(trt__GetProfilesResponse.Profiles->Name!=NULL){printf("Profiles Name:%s  \n", trt__GetProfilesResponse.Profiles->Name);}if (trt__GetProfilesResponse.Profiles->token != NULL){trt__GetStreamUri.ProfileToken = trt__GetProfilesResponse.Profiles->token;tptz__GetStatus.ProfileToken = trt__GetProfilesResponse.Profiles->token;tptz__ContinuousMove.ProfileToken = trt__GetProfilesResponse.Profiles->token;tptz__Stop.ProfileToken = trt__GetProfilesResponse.Profiles->token;tptz__AbsoluteMove.ProfileToken  = trt__GetProfilesResponse.Profiles->token;tptz__RelativeMove.ProfileToken = trt__GetProfilesResponse.Profiles->token;return true;}elsereturn false;}elsereturn false;}
}std::string OnvifSDK::GetUri(enum tt__TransportProtocol transtype)
{trt__GetStreamUri.StreamSetup = (struct tt__StreamSetup*)soap_malloc(soap, sizeof(struct tt__StreamSetup));trt__GetStreamUri.StreamSetup->Stream =  tt__StreamType__RTP_Unicast;//stream typetrt__GetStreamUri.StreamSetup->Transport = (struct tt__Transport*)soap_malloc(soap, sizeof(struct tt__Transport));trt__GetStreamUri.StreamSetup->Transport->Protocol = transtype;trt__GetStreamUri.StreamSetup->Transport->Tunnel = 0;soap_wsse_add_UsernameTokenDigest(soap, "", UserName.c_str(), PassWord.c_str());soap_call___trt__GetStreamUri(soap, capa_resp.Capabilities->Media->XAddr, NULL, &trt__GetStreamUri, &trt__GetStreamUriResponse);if (soap->error)return "";elsereturn std::string(trt__GetStreamUriResponse.MediaUri->Uri);
}bool OnvifSDK::GetStstus(float* pvalue, float* tvalue, float* zvalue)
{soap_wsse_add_UsernameTokenDigest(soap, "", UserName.c_str(), PassWord.c_str());soap_call___tptz__GetStatus(soap, capa_resp.Capabilities->PTZ->XAddr, NULL, &tptz__GetStatus, &tptz__GetStatusResponse);if (soap->error)return false;else{*pvalue = tptz__GetStatusResponse.PTZStatus->Position->PanTilt->x;*tvalue = tptz__GetStatusResponse.PTZStatus->Position->PanTilt->y;*zvalue = tptz__GetStatusResponse.PTZStatus->Position->Zoom->x;return true;}
}void OnvifSDK::ControlPTZ(int control, bool control_type, int speed)
{memset(&tptz__ContinuousMove, 0x0, sizeof(tptz__ContinuousMove));memset(&tptz__ContinuousMoveResponse, 0x0, sizeof(tptz__ContinuousMoveResponse));tptz__ContinuousMove.ProfileToken = trt__GetProfilesResponse.Profiles->token;tptz__ContinuousMove.Velocity = (struct tt__PTZSpeed*)soap_malloc(soap, sizeof(tt__PTZSpeed));memset(tptz__ContinuousMove.Velocity, 0x0, sizeof(tt__PTZSpeed));tptz__ContinuousMove.Velocity->PanTilt = (struct tt__Vector2D*)soap_malloc(soap, sizeof(tt__Vector2D));memset(tptz__ContinuousMove.Velocity->PanTilt, 0x0, sizeof(tt__Vector2D));tptz__ContinuousMove.Velocity->Zoom = (struct tt__Vector1D*)soap_malloc(soap, sizeof(tt__Vector1D));memset(tptz__ContinuousMove.Velocity->Zoom, 0x0, sizeof(tt__Vector1D));tptz__ContinuousMove.Velocity->PanTilt->x = 0;tptz__ContinuousMove.Velocity->PanTilt->y = 0;tptz__ContinuousMove.Velocity->Zoom->x = 0;soap_wsse_add_UsernameTokenDigest(soap, "", UserName.c_str(), PassWord.c_str());if (control_type){switch (control){case 0:tptz__ContinuousMove.Velocity->PanTilt->y = (float)speed / 10;break;case 1:tptz__ContinuousMove.Velocity->PanTilt->y = (float)speed / 10 * -1.0;break;case 2:tptz__ContinuousMove.Velocity->PanTilt->x = (float)speed / 10 * -1.0;break;case 3:tptz__ContinuousMove.Velocity->PanTilt->x = (float)speed / 10;break;case 4:tptz__ContinuousMove.Velocity->PanTilt->y = (float)speed / 10;tptz__ContinuousMove.Velocity->PanTilt->x = (float)speed / 10 * -1.0;break;case 5:tptz__ContinuousMove.Velocity->PanTilt->y = (float)speed / 10;tptz__ContinuousMove.Velocity->PanTilt->x = (float)speed / 10;break;case 6:tptz__ContinuousMove.Velocity->PanTilt->y = (float)speed / 10 * -1.0;tptz__ContinuousMove.Velocity->PanTilt->x = (float)speed / 10 * -1.0;break;case 7:tptz__ContinuousMove.Velocity->PanTilt->y = (float)speed / 10 * -1.0;tptz__ContinuousMove.Velocity->PanTilt->x = (float)speed / 10;break;case 8:tptz__ContinuousMove.Velocity->Zoom->x = (float)speed / 10;break;case 9:tptz__ContinuousMove.Velocity->Zoom->x = (float)speed / 10 * -1.0;break;default:return;}int ret = soap_call___tptz__ContinuousMove(soap, capa_resp.Capabilities->PTZ->XAddr, NULL, &tptz__ContinuousMove, &tptz__ContinuousMoveResponse);if (SOAP_OK == ret){printf("RelativeMove----OK\n");}}else{TrueFlag = xsd__boolean__true_;tptz__Stop.PanTilt = &TrueFlag;tptz__Stop.Zoom = &TrueFlag;soap_call___tptz__Stop(soap, capa_resp.Capabilities->PTZ->XAddr, NULL, &tptz__Stop, &tptz__StopResponse);}
}void OnvifSDK::SetPTZ(float pvalue, float tvalue, float zvalue)
{tptz__AbsoluteMove.Position->PanTilt->x = pvalue;tptz__AbsoluteMove.Position->PanTilt->y = tvalue;tptz__AbsoluteMove.Position->Zoom->x = zvalue;soap_wsse_add_UsernameTokenDigest(soap, "", UserName.c_str(), PassWord.c_str());int ret = soap_call___tptz__AbsoluteMove(soap, capa_resp.Capabilities->PTZ->XAddr, NULL, &tptz__AbsoluteMove, &tptz__AbsoluteMoveResponse);
}void OnvifSDK::SetMoveStep(ptz_common commond, float move_step)
{memset(&tptz__RelativeMove, 0x0, sizeof(tptz__RelativeMove));memset(&tptz__RelativeMoveResponse, 0x0, sizeof(tptz__RelativeMoveResponse));//    printf("__sizeProfiles: %d\n", reponse_pro.__sizeProfiles);//    printf("token: %s\n", reponse_pro.Profiles->token);tptz__RelativeMove.ProfileToken = trt__GetProfilesResponse.Profiles->token;tptz__RelativeMove.Translation = (struct tt__PTZVector*)soap_malloc(soap, sizeof(tt__PTZVector));memset(tptz__RelativeMove.Translation, 0x0, sizeof(tt__PTZVector));tptz__RelativeMove.Translation->PanTilt = (struct tt__Vector2D*)soap_malloc(soap, sizeof(tt__Vector2D));memset(tptz__RelativeMove.Translation->PanTilt, 0x0, sizeof(tt__Vector2D));tptz__RelativeMove.Translation->Zoom = (struct tt__Vector1D*)soap_malloc(soap, sizeof(tt__Vector1D));memset(tptz__RelativeMove.Translation->Zoom, 0x0, sizeof(tt__Vector1D));if (move_step >= 1)move_step = 0.99999;switch (commond){case PTZ_LEFT:tptz__RelativeMove.Translation->PanTilt->x = move_step;break;case PTZ_RIGHT:tptz__RelativeMove.Translation->PanTilt->x = -move_step;break;case PTZ_UP:tptz__RelativeMove.Translation->PanTilt->y = -move_step;break;case PTZ_DOWN:tptz__RelativeMove.Translation->PanTilt->y = move_step;break;case PTZ_LEFTUP:tptz__RelativeMove.Translation->PanTilt->x = move_step;tptz__RelativeMove.Translation->PanTilt->y = -move_step;break;case PTZ_LEFTDOWN:tptz__RelativeMove.Translation->PanTilt->x = move_step;tptz__RelativeMove.Translation->PanTilt->y = move_step;break;case PTZ_RIGHTUP:tptz__RelativeMove.Translation->PanTilt->x = -move_step;tptz__RelativeMove.Translation->PanTilt->y = -move_step;break;case PTZ_RIGHTDOWN:tptz__RelativeMove.Translation->PanTilt->x = -move_step;tptz__RelativeMove.Translation->PanTilt->y = move_step;break;case PTZ_ZOOMIN:tptz__RelativeMove.Translation->Zoom->x = move_step;break;case PTZ_ZOOMOUT:tptz__RelativeMove.Translation->Zoom->x = -move_step;break;default:soap_destroy(soap);soap_end(soap);soap_free(soap);return ;break;}soap_wsse_add_UsernameTokenDigest(soap, "", UserName.c_str(), PassWord.c_str());int result = soap_call___tptz__RelativeMove(soap, capa_resp.Capabilities->PTZ->XAddr, NULL, &tptz__RelativeMove, &tptz__RelativeMoveResponse);if (SOAP_OK == result)printf("RelativeMove----OK\n");else{printf("RelativeMove----faild\n");//printf("soap error: %d--%d, %s, %s\n", __LINE__, soap->error, *soap_faultcode(soap), *soap_faultstring(soap));}
}

鉴权是要用到openssl库的,不过嵌入式下集成一个大库你可能不太乐意,也可以用下面sha1文件中的实现 是等效的啊! sha1.c代码见工程

#include "soapH.h"
#include "soapStub.h"
#include "PTZBinding.nsmap"#ifdef WITH_OPENSSL
#include "dom.c"
#include "mecevp.c"
#include "smdevp.c"
#include "threads.c"
#include "wsaapi.c"
#include "wsseapi.c"
#else
#include "sha1.c"
#endif

实现中鉴权部分涉及使用:

#ifdef WITH_OPENSSL
#else
void OnvifSDK::calc_nonce(struct soap* soap, char nonce[SOAP_WSSE_NONCELEN])
{int i;time_t r = time(NULL);memcpy(nonce, &r, 4);for (i = 4; i < SOAP_WSSE_NONCELEN; i += 4){r = soap_random;memcpy(nonce + i, &r, 4);}
}_wsse__Security* OnvifSDK::soap_wsse_add_Security(struct soap* soap)
{/* if we don't have a SOAP Header, create one *///?? soap_header(soap);  此处无法编译 到源码去拷贝if (soap->header == NULL){if ((soap->header = (struct SOAP_ENV__Header*)soap_malloc(soap, sizeof(struct SOAP_ENV__Header))))soap_default_SOAP_ENV__Header(soap, soap->header);}/* if we don't have a wsse:Security element in the SOAP Header, create one */if (!soap->header->wsse__Security){soap->header->wsse__Security = (_wsse__Security*)soap_malloc(soap, sizeof(_wsse__Security));soap_default__wsse__Security(soap, soap->header->wsse__Security);}return soap->header->wsse__Security;
}int OnvifSDK::soap_wsse_add_UsernameTokenText(struct soap* soap, const char* id,const char* username, const char* password)
{_wsse__Security* security = soap_wsse_add_Security(soap);/* allocate a UsernameToken if we don't have one already */if (!security->UsernameToken)security->UsernameToken = (_wsse__UsernameToken*)soap_malloc(soap, sizeof(_wsse__UsernameToken));soap_default__wsse__UsernameToken(soap, security->UsernameToken);/* populate the UsernameToken */security->UsernameToken->wsu__Id = soap_strdup(soap, id);security->UsernameToken->Username = soap_strdup(soap, username);/* allocate and populate the Password */if (password){security->UsernameToken->Password = (_wsse__Password*)soap_malloc(soap, sizeof(_wsse__Password));soap_default__wsse__Password(soap, security->UsernameToken->Password);security->UsernameToken->Password->Type = (char*)wsse_PasswordTextURI;security->UsernameToken->Password->__item = soap_strdup(soap, password);}return SOAP_OK;
}int OnvifSDK::soap_wsse_add_UsernameTokenDigest(struct soap* soap, const char* id,const char* username, const char* password)
{_wsse__Security* security = soap_wsse_add_Security(soap);time_t now = time(NULL);const char* created = soap_dateTime2s(soap, now);char HA[SOAP_SMD_SHA1_SIZE], HABase64[29];char nonce[SOAP_WSSE_NONCELEN], *nonceBase64;/* generate a nonce */calc_nonce(soap, nonce);nonceBase64 = soap_s2base64(soap, (unsigned char*)nonce, NULL, SOAP_WSSE_NONCELEN);/* The specs are not clear: compute digest over binary nonce or base64 nonce? *//* compute SHA1(created, nonce, password) *//*  // boost计算结果不对,应该是我的使用方法不对unsigned int Digest[5] = {0};boost::uuids::detail::sha1  sha;sha.process_bytes(nonce, strlen(nonce));sha.process_bytes(created, strlen(created));sha.process_bytes(password, strlen(password));sha.get_digest(Digest);for (int n=0,i=0; n<SOAP_SMD_SHA1_SIZE; ){HA[n++] = (Digest[i] >> 24) & 0xFF;HA[n++] = (Digest[i] >> 16) & 0xFF;HA[n++] = (Digest[i] >> 8) & 0xFF;HA[n++] = Digest[i] & 0xFF;i++;}*/calc_digest(soap, created, nonce, SOAP_WSSE_NONCELEN, password, HA);// calc_digest(soap, created, nonce, SOAP_WSSE_NONCELEN, password, HA);/*calc_digest(soap, created, nonceBase64, strlen(nonceBase64), password, HA);*/soap_s2base64(soap, (unsigned char*)HA, HABase64, SOAP_SMD_SHA1_SIZE);/* populate the UsernameToken with digest */soap_wsse_add_UsernameTokenText(soap, id, username, HABase64);/* populate the remainder of the password, nonce, and created */security->UsernameToken->Password->Type = (char*)wsse_PasswordDigestURI;security->UsernameToken->Nonce = (struct wsse__EncodedString*)soap_malloc(soap, sizeof(struct wsse__EncodedString));if (!security->UsernameToken->Nonce)return soap->error = SOAP_EOM;soap_default_wsse__EncodedString(soap, security->UsernameToken->Nonce);security->UsernameToken->Nonce->__item = nonceBase64;security->UsernameToken->Nonce->EncodingType = (char*)wsse_Base64BinaryURI;security->UsernameToken->wsu__Created = soap_strdup(soap, created);return SOAP_OK;
}void OnvifSDK::calc_digest(struct soap* soap, const char* created, const char* nonce, int noncelen, const char* password, char hash[SOAP_SMD_SHA1_SIZE])
{SHA1Context sha;SHA1Reset(&sha);SHA1Input(&sha, (unsigned char*)nonce, noncelen);SHA1Input(&sha, (unsigned char*)created, strlen(created));SHA1Input(&sha, (unsigned char*)password, strlen(password));if (!SHA1Result(&sha))fprintf(stderr, "ERROR-- could not compute message digest\n");else{int j = 0;for (int i = 0; i < 5; i++){hash[j++] = sha.Message_Digest[i] >> 24;hash[j++] = sha.Message_Digest[i] >> 16;hash[j++] = sha.Message_Digest[i] >> 8;hash[j++] = sha.Message_Digest[i] >> 0;}}
}void OnvifSDK::TokenTimestmap(struct soap* pSoap, time_t lifetime /*= TOKEN_TIMESTAMP*/)
{soap_wsse_add_Timestamp(pSoap, "Time", lifetime);
}int OnvifSDK::soap_wsse_add_Timestamp(struct soap* soap, const char* id, time_t lifetime)
{_wsse__Security* security = soap_wsse_add_Security(soap);time_t now = time(NULL);char* created = soap_strdup(soap, soap_dateTime2s(soap, now));char* expired = lifetime ? soap_strdup(soap, soap_dateTime2s(soap, now + lifetime)) : NULL;/* allocate a Timestamp if we don't have one already */if (!security->wsu__Timestamp)security->wsu__Timestamp = (_wsu__Timestamp*)soap_malloc(soap, sizeof(_wsu__Timestamp));soap_default__wsu__Timestamp(soap, security->wsu__Timestamp);/* populate the wsu:Timestamp element */security->wsu__Timestamp->wsu__Id = soap_strdup(soap, id);security->wsu__Timestamp->Created = created;security->wsu__Timestamp->Expires = expired;return SOAP_OK;
}#endif

完整工程下载

ONVIF PTZ控制海康云台相机相关推荐

  1. uniapp海康云台插件可实时操控摄像头

    功能预览 一.引入大牛封装的海康云台插件(付费的) 1.在DCloud插件市场,下载插件海康摄像头控制插件下载地址 第一步:登录你的HBuilder账号 第二步:点击试用 第三步:选择你要试用的改插件 ...

  2. pyQT5 学习使用 笔记 六 pyQt5+opencv 显示海康GIGE相机动态视频流

    opencv 读取 海康GIGE相机视频流 新项目中我们需要使用opencv读取海康威视的工业相机 MV-CA060-10GM 的视频流进行处理.那么首先我们要读取到相机的视频流,总所周知 openc ...

  3. 海康摄像头二次开发详解,包含海康摄像头登录、海康云台控制、视频下载等功能

    海康摄像头二次开发详解 准备 海康摄像头SDK开发下载路径: 开发过程中遇到的问题记录: 添加maven依赖 下面代码中会出现的实体类 CameraManage实体类: ControlDto实体类: ...

  4. 使用阿里云物联网平台IoT Studio控制海康摄像头旋转

    需求: 在温室大棚的物联网监控系统里,安装了带云台控制的摄像头,海康自带的app是可以实现云台控制(转动,放大缩小),但是嵌入网页的播放器,没有这个功能,而客户又希望通过网页去控制摄像头,捕捉特定的植 ...

  5. 通过onvif抓取海康摄像头图片,以及解决海康摄像头抓取图片需要验证问题,实现摄像头一段时间换一个地方的同时抓取一张图片。

    1.实现海康摄像头的图片的抓取. 思路:1.首先获取图片的url,2通过java实现图片的下载 1.使用onvif获取图片的url //首先获取OnvifDevice的对象OnvifDevice od ...

  6. 相机开发:海康板卡相机开发

    海康相机开发 板卡相机开发IO设置 参数保存 板卡相机开发IO设置 https://my.oschina.net/u/4322890/blog/4260926 参数保存 https://blog.cs ...

  7. 海康云台监控夜间彩色设置

    画面过爆 更改后效果,柔和很多. 解决方法: 日夜转换:白天 背光:宽动态"开启" 强光抑制"开启"

  8. 使用Onvif抓取海康摄像头图片需要账号密码验证问题

    1.首先,使用 Media 模块中的 GetSnapshotUri接口获取图片的url,通过获取的url可以在浏览器上查看图片也可以用java代码下载.但是,当我在浏览器上查看时让我输入账号和密码,如 ...

  9. 海康工业相机功能模块-IO输入输出控制

    海康工业相机功能模块sdk调用介绍 IO输入输出控制 前言 IO输入 IO输出 前言 机器视觉行业里面,相机作为最重要的图像传感器,除了主要的拍摄功能外,它也承担了一部分信号控制功能. 一方面能够接受 ...

最新文章

  1. poj 2513(欧拉路径+字典树映射)
  2. 51Nod1916 购物
  3. hibernate mysql 映射_hibernate与mysql映射类型对应表与mysql导入导出
  4. 循环队列(0965)
  5. Javascript中的arguments数组对象
  6. 李宏毅机器学习课程8~~~keras
  7. opencv 把3通道图像转成单通道_小强学Python+OpenCV之-1.4.3图像(矩阵)加减运算
  8. PHP array_filter()函数与示例
  9. win7装ORACLE提示操作系统未验证或 Service Pack 未执行
  10. C#调用存储过程详解
  11. java_security之base64原理解析以及三种代码的实现方式
  12. 【java】画图和监听事件的应用
  13. 科大讯飞2019机械核心部件寿命预测,亚军方案
  14. 怎样做一份良好的竞品分析?通常有哪些方法?
  15. CAJViewer的下载与使用
  16. 网游无间道:你所忽略的托儿
  17. 【枚举与countDownLatch的应用】
  18. 仿瑞吉外卖 【手机登陆功能换成邮件登陆】
  19. 基于Edge浏览器的沙拉划词插件使用教程(好用的翻译插件)
  20. 如何将程序打包成exe

热门文章

  1. 如何打造个人技术影响力
  2. Vue3+node.js网易云音乐实战项目(三)
  3. 一次关于缓存行的切身体验
  4. 券商交易接口是什么?
  5. 小米4 第三方re奇兔_小米、vivo、一加等宣布Android 11 beta版本适配计划
  6. R语言安装REmap包及安装baidumap报错问题和使用
  7. 智能控制基础实验3:数字PID控制
  8. 单片机_第4章 单片机的C51语言
  9. Android+音视频 全新面试题,求职/跳槽吊打面试官
  10. 计算机组装人员的职责,装配技术员岗位的基本职责