图漾官网Sample_V1版本C++语言完整参考例子---单相机版本
文章目录
- 1.参考例子
主要梳理了图漾官网Sample_V1版本的例子
1.参考例子
主要增加了从storage区域读取相机参数的设置,使用图漾PercipioViewer软件,如何将相机参数保存到srorage区,可参考链接:保存相机参数操作
注:在进行保存参数前,需要关闭相机各个组件取流
具体代码如下:
#include <limits>
#include <cassert>
#include <cmath>
#include "../common/common.hpp"
#include <TYImageProc.h>
#include <chrono>//设置相机参数开关,默认使用相机内保存的参数。(使用保存的参数,也可以修改参数)
//不同型号相机具备不同的参数属性,可以使用PercipioViewer看图软件确认相机支持的参数属性和参数取值范围
bool setParameters = false;//深度图对齐到彩色图开关,置1则将深度图对齐到彩色图坐标系,置0则不对齐
//因彩色图对齐到深度图时会有部分深度缺失的区域丢失彩色信息,因此默认使用深度图对齐到彩色图方式
#define MAP_DEPTH_TO_COLOR 0
//开启以下深度图渲染显示将会降低帧率
DepthViewer depthViewer0("OrgDepth");//用于显示渲染后的原深度图
DepthViewer depthViewer1("FillHoleDepth");//用于显示渲染后的填洞处理之后的深度图
DepthViewer depthViewer2("SpeckleFilterDepth"); //用于显示渲染后的经星噪滤波过的深度图
DepthViewer depthViewer3("EnhenceFilterDepth"); //用于显示渲染后的经时域滤波过的深度图
DepthViewer depthViewer4("MappedDepth"); //用于显示渲染后的对齐到彩色图坐标系的深度图//事件回调
void eventCallback(TY_EVENT_INFO *event_info, void *userdata)
{if (event_info->eventId == TY_EVENT_DEVICE_OFFLINE) {LOGD("=== Event Callback: Device Offline!");*(bool*)userdata = true;// Note: // Please set TY_BOOL_KEEP_ALIVE_ON OFF feature to false if you need to debug with breakpoint!}else if (event_info->eventId == TY_EVENT_LICENSE_ERROR) {LOGD("=== Event Callback: License Error!");}
}//数据格式转换
//cv pixel format to TY_PIXEL_FORMAT
static int cvpf2typf(int cvpf)
{switch(cvpf){case CV_8U: return TY_PIXEL_FORMAT_MONO;case CV_8UC3: return TY_PIXEL_FORMAT_RGB;case CV_16UC1: return TY_PIXEL_FORMAT_DEPTH16;default: return TY_PIXEL_FORMAT_UNDEFINED;}
}//数据格式转换
//mat to TY_IMAGE_DATA
static void mat2TY_IMAGE_DATA(int comp, const cv::Mat& mat, TY_IMAGE_DATA& data)
{data.status = 0;data.componentID = comp;data.size = mat.total() * mat.elemSize();data.buffer = mat.data;data.width = mat.cols;data.height = mat.rows;data.pixelFormat = cvpf2typf(mat.type());
}//回调数据
struct CallbackData {int index;TY_DEV_HANDLE hDevice;TY_CAMERA_INTRINSIC* intri_depth;TY_CAMERA_INTRINSIC* intri_color;TY_CAMERA_CALIB_INFO depth_calib;TY_CAMERA_CALIB_INFO color_calib;float scale_unit;bool saveOneFramePoint3d;int fileIndex;bool isTof;
};
CallbackData cb_data;//通过内参实训深度图转点云,方式供参考
//depth to pointcloud
cv::Mat depthToWorld(float* intr, const cv::Mat& depth, float scale_unit = 1.0)
{cv::Mat world(depth.rows, depth.cols, CV_32FC3);float cx = intr[2];float cy = intr[5];float inv_fx = 1.0f / intr[0];float inv_fy = 1.0f / intr[4];for (int r = 0; r < depth.rows; r++){uint16_t* pSrc = (uint16_t*)depth.data + r * depth.cols;cv::Vec3f* pDst = (cv::Vec3f*)world.data + r * depth.cols;for (int c = 0; c < depth.cols; c++){uint16_t z = pSrc[c] * scale_unit;if (z == 0) {pDst[c][0] = NAN;pDst[c][1] = NAN;pDst[c][2] = NAN;}else {pDst[c][0] = (c - cx) * z * inv_fx;pDst[c][1] = (r - cy) * z * inv_fy;pDst[c][2] = z;}}}return world;
}//输出畸变校正的彩色图,并实现深度图对齐到彩色图
static void doRegister(const TY_CAMERA_CALIB_INFO& depth_calib, const TY_CAMERA_CALIB_INFO& color_calib, const cv::Mat& depth, const float f_scale_unit, const cv::Mat& color, cv::Mat& undistort_color, cv::Mat& out, bool map_depth_to_color
)
{// do undistortionTY_IMAGE_DATA src;src.width = color.cols;src.height = color.rows;src.size = color.size().area() * 3;src.pixelFormat = TY_PIXEL_FORMAT_RGB;src.buffer = color.data;undistort_color = cv::Mat(color.size(), CV_8UC3);TY_IMAGE_DATA dst;dst.width = color.cols;dst.height = color.rows;dst.size = undistort_color.size().area() * 3;dst.buffer = undistort_color.data;dst.pixelFormat = TY_PIXEL_FORMAT_RGB;ASSERT_OK(TYUndistortImage(&color_calib, &src, NULL, &dst));// do registerif (map_depth_to_color) {out = cv::Mat::zeros(undistort_color.size(), CV_16U);ASSERT_OK(TYMapDepthImageToColorCoordinate(&depth_calib,depth.cols, depth.rows, depth.ptr<uint16_t>(),&color_calib,out.cols, out.rows, out.ptr<uint16_t>(), f_scale_unit));}else {out = depth;}
}//帧处理
void frameHandler(TY_FRAME_DATA* frame, void* userdata)
{CallbackData* pData = (CallbackData*) userdata;LOGD("=== Get frame %d", ++pData->index);std::vector<TY_VECT_3F> P3dtoColor;//对齐到color的点云cv::Mat depth, color, p3d, newP3d;//auto StartParseFrame = std::chrono::steady_clock::now();//解析帧parseFrame(*frame, &depth, 0, 0, &color);//拿深度图和color图//parseFrame(*frame, &depth, 0, 0, 0);//只拿深度图// auto ParseFrameFinished = std::chrono::steady_clock::now(); // auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>(ParseFrameFinished - StartParseFrame); // LOGI("*******ParseFrame spend Time : %lld", duration2);//填洞开关,开启后会降低帧率bool FillHole = 0;//星噪滤波开关,深度图中离散点降噪处理bool SpeckleFilter = 1;//时域滤波,可降低单点抖动,提升点云平面度bool EnhenceFilter = 0;//深度图处理if (!depth.empty()){if (pData->isTof){//r如果是TOF相机,深度图需要做畸变校正,如TM26X相机和TM421,而双目相机不需要执行该步骤TY_IMAGE_DATA src;src.width = depth.cols;src.height = depth.rows;src.size = depth.size().area() * 2;src.pixelFormat = TY_PIXEL_FORMAT_DEPTH16;src.buffer = depth.data;cv::Mat undistort_depth = cv::Mat(depth.size(), CV_16U);TY_IMAGE_DATA dst;dst.width = depth.cols;dst.height = depth.rows;dst.size = undistort_depth.size().area() * 2;dst.buffer = undistort_depth.data;dst.pixelFormat = TY_PIXEL_FORMAT_DEPTH16;ASSERT_OK(TYUndistortImage(&pData->depth_calib, &src, NULL, &dst));depth = undistort_depth.clone();}if (FillHole){//深度图填洞处理DepthInpainter inpainter;inpainter._kernelSize = 10;inpainter._maxInternalHoleToBeFilled = 1800;inpainter._fillAll = false;inpainter.inpaint(depth, depth, cv::Mat());depthViewer1.show(depth);}if (SpeckleFilter){//使用星噪滤波TY_IMAGE_DATA sfFilteredDepth;cv::Mat filteredDepth(depth.size(), depth.type());filteredDepth = depth.clone();mat2TY_IMAGE_DATA(TY_COMPONENT_DEPTH_CAM, filteredDepth, sfFilteredDepth);struct DepthSpeckleFilterParameters sfparam = DepthSpeckleFilterParameters_Initializer;sfparam.max_speckle_size = 300;//噪点面积小于该值将被过滤sfparam.max_speckle_diff = 64;//相邻像素视差大于该值将被视为噪点TYDepthSpeckleFilter(&sfFilteredDepth, &sfparam);//显示星噪滤波后深度图渲染depthViewer2.show(filteredDepth);//点云, pointcloud in CV_32FC3 formatnewP3d = depthToWorld(pData->intri_depth->data, filteredDepth,pData->scale_unit);depth = filteredDepth.clone();保存滤波后的深度图//char file[32];//sprintf(file, "depth-%d.png", pData->fileIndex++);//cv::imwrite(file, filteredDepth);}if (EnhenceFilter){//使用时域滤波TY_IMAGE_DATA efFilteredDepthin, efFilteredDepthout;cv::Mat filteredDepth1(depth.size(), depth.type());cv::Mat filteredDepth2(depth.size(), depth.type());filteredDepth1 = depth.clone();mat2TY_IMAGE_DATA(TY_COMPONENT_DEPTH_CAM, filteredDepth1, efFilteredDepthin);mat2TY_IMAGE_DATA(TY_COMPONENT_DEPTH_CAM, filteredDepth2, efFilteredDepthout);struct DepthEnhenceParameters efparam = DepthEnhenceParameters_Initializer;efparam.sigma_s = 0;//空间滤波系数efparam.sigma_r = 0;//深度滤波系数efparam.outlier_win_sz = 0;//以像素为单位的滤波窗口efparam.outlier_rate = 0.f;//噪音过滤系数TY_IMAGE_DATA *guide = nullptr;TYDepthEnhenceFilter(&efFilteredDepthin, 3, guide, &efFilteredDepthout, &efparam);//显示时域滤波后深度图渲染depthViewer3.show(filteredDepth2);//点云, pointcloud in CV_32FC3 formatnewP3d = depthToWorld(pData->intri_depth->data, filteredDepth2, pData->scale_unit);depth = filteredDepth2.clone();保存滤波后的深度图//char file[32];//sprintf(file, "depth-%d.png", pData->fileIndex++);//cv::imwrite(file, filteredDepth);}else if (!FillHole&&!SpeckleFilter&&!EnhenceFilter){//显示原深度图渲染depthViewer0.show(depth);//原点云p3d = depthToWorld(pData->intri_depth->data, depth, pData->scale_unit);}}//彩色图处理cv::Mat color_data_mat,p3dtocolorMat;if (!color.empty()){//显示原彩色图//imshow("orgColor", color);cv::Mat undistort_color, MappedDepth;if (MAP_DEPTH_TO_COLOR){auto BeforedoRegister = std::chrono::steady_clock::now();//彩色图去畸变,并将深度图对齐到彩色图坐标系doRegister(pData->depth_calib, pData->color_calib, depth, pData->scale_unit, color,undistort_color, MappedDepth, MAP_DEPTH_TO_COLOR);//数据格式转换cv::cvtColor(undistort_color, color_data_mat, CV_BGR2RGB);//生成对齐到彩色图坐标系的点云,两种方法//方法一:生成点云放在TY_VECT_3F---P3dtoColorP3dtoColor.resize(MappedDepth.size().area());ASSERT_OK(TYMapDepthImageToPoint3d(&pData->color_calib, MappedDepth.cols, MappedDepth.rows, (uint16_t*)MappedDepth.data, &P3dtoColor[0],pData->scale_unit));//方法二:生成点云放在32FC3 Mat---p3dtocolorMat//p3dtocolorMat = depthToWorld(pData->intri_color->data, MappedDepth);auto AfterdoRegister = std::chrono::steady_clock::now(); auto duration3 = std::chrono::duration_cast<std::chrono::microseconds>(AfterdoRegister - BeforedoRegister);LOGI("*******do Rgb Undistortion--MapDepthToColor--P3D spend Time : %lld", duration3); //显示畸变校正后的彩色图imshow("undistort_color", undistort_color);//显示对齐到彩色图坐标系的深度图depthViewer4.show(MappedDepth);}else{//彩色图去畸变,未对齐的深度图doRegister(pData->depth_calib, pData->color_calib, depth, pData->scale_unit, color, undistort_color, MappedDepth, MAP_DEPTH_TO_COLOR);//显示畸变校正后的彩色图imshow("undistort_color", undistort_color);}}//保存点云//save pointcloudif (pData->saveOneFramePoint3d) {char file[32];if (MAP_DEPTH_TO_COLOR){LOGD("Save p3dtocolor now!!!");//保存对齐到color坐标系XYZRGB格式彩色点云sprintf(file, "p3dtocolor-%d.xyz", pData->fileIndex++);writePointCloud((cv::Point3f*)p3dtocolorMat.data, (const cv::Vec3b*)color_data_mat.data, p3dtocolorMat.total(), file, PC_FILE_FORMAT_XYZ);}else{LOGD("Save point3d now!!!");//保存XYZ格式点云sprintf(file, "points-%d.xyz", pData->fileIndex++);writePointCloud((cv::Point3f*)newP3d.data, 0, newP3d.total(), file, PC_FILE_FORMAT_XYZ);}pData->saveOneFramePoint3d = false;}//归还Buffer队列LOGD("=== Re-enqueue buffer(%p, %d)", frame->userBuffer, frame->bufferSize);ASSERT_OK( TYEnqueueBuffer(pData->hDevice, frame->userBuffer, frame->bufferSize) );
}int main(int argc, char* argv[])
{std::string ID, IP;TY_INTERFACE_HANDLE hIface = NULL;TY_DEV_HANDLE hDevice = NULL;TY_CAMERA_INTRINSIC intri_depth;TY_CAMERA_INTRINSIC intri_color;int32_t resend = 1;bool isTof = 0;for(int i = 1; i < argc; i++){if(strcmp(argv[i], "-id") == 0){ID = argv[++i];} else if(strcmp(argv[i], "-ip") == 0) {IP = argv[++i];} else if(strcmp(argv[i], "-h") == 0){LOGI("Usage: SimpleView_Callback [-h] [-id <ID>]");return 0;}}LOGD("=== Init lib");ASSERT_OK(TYInitLib());TY_VERSION_INFO ver;ASSERT_OK(TYLibVersion(&ver));LOGD(" - lib version: %d.%d.%d", ver.major, ver.minor, ver.patch);std::vector<TY_DEVICE_BASE_INFO> selected;//选择相机ASSERT_OK(selectDevice(TY_INTERFACE_ALL, ID, IP, 1, selected));ASSERT(selected.size() > 0);//默认加载第一个相机TY_DEVICE_BASE_INFO& selectedDev = selected[0];//const std::string actualBrand = selected[0].modelName;//打开接口和设备ASSERT_OK(TYOpenInterface(selectedDev.iface.id, &hIface));ASSERT_OK(TYOpenDevice(hIface, selectedDev.id, &hDevice));//对时设置LOGD("Set type of time sync mechanism");ASSERT_OK(TYSetEnum(hDevice, TY_COMPONENT_DEVICE, TY_ENUM_TIME_SYNC_TYPE, TY_TIME_SYNC_TYPE_HOST));LOGD("Wait for time sync ready");while (1){bool sync_ready;ASSERT_OK(TYGetBool(hDevice, TY_COMPONENT_DEVICE, TY_BOOL_TIME_SYNC_READY, &sync_ready));if (sync_ready){break;}MSLEEP(10);}//设置相机log输出等级,VERBOSE > DEBUG > INFO > WARNING > ERROR//ASSERT_OK(TYSetLogLevel(TY_LOG_LEVEL_ERROR));//ASSERT_OK(TYAppendLogToFile("test_log.txt", TY_LOG_LEVEL_DEBUG)); //相机日志输出到文件内,搭配关闭输出TYRemoveLogFile//使用相机内保存参数if (!setParameters){std::string js_data;int ret;ret = load_parameters_from_storage(hDevice, js_data);//使用相机内保存参数if (ret == TY_STATUS_ERROR){LOGD("no save parameters in the camera");setParameters = true;}else if (ret != TY_STATUS_OK){LOGD("Failed: error %d(%s)", ret, TYErrorString(ret));setParameters = true;}}//使能彩色相机//try to enable color cameraLOGD("Has RGB camera, open RGB cam");ASSERT_OK(TYEnableComponents(hDevice, TY_COMPONENT_RGB_CAM));//设置彩色相机像素格式和分辨率if (setParameters){LOGD("=== Configure feature, set RGB resolution");//方法一:直接设置像素格式和分辨率//ASSERT_OK(TYSetEnum(hDevice, TY_COMPONENT_RGB_CAM, TY_ENUM_IMAGE_MODE, TY_IMAGE_MODE_BAYER8GB_640x480));//ASSERT_OK(TYSetEnum(hDevice, TY_COMPONENT_RGB_CAM, TY_ENUM_IMAGE_MODE, TY_IMAGE_MODE_YUYV_1920x1080));//不同型号图漾相机的彩色像素格式和分辨率不同,具体可见相机规格书;//方法二:通过枚举相机支持的图像模式,结合图像宽度选定分辨率,不关注像素格式TY_STATUS status = TY_STATUS_OK;if (TY_COMPONENT_RGB_CAM) {std::vector<TY_ENUM_ENTRY> image_mode_list;status = get_feature_enum_list(hDevice, TY_COMPONENT_RGB_CAM, TY_ENUM_IMAGE_MODE, image_mode_list);for (int idx = 0; idx < image_mode_list.size(); idx++) {TY_ENUM_ENTRY& entry = image_mode_list[idx];//try to select a resolutionif (TYImageWidth(entry.value) == 640) {LOGD("Select RGB Image Mode: %s", entry.description);int err = TYSetEnum(hDevice, TY_COMPONENT_RGB_CAM, TY_ENUM_IMAGE_MODE, entry.value);ASSERT(err == TY_STATUS_OK || err == TY_STATUS_NOT_PERMITTED);break;}}}}//读取彩色相机标定数据//TY_STRUCT_CAM_CALIB_DATA内参是相机最大分辨率的内参//TY_STRUCT_CAM_INTRINSIC内参是相机当前分辨率的内参LOGD("=== Get color intrinsic");ASSERT_OK(TYGetStruct(hDevice, TY_COMPONENT_RGB_CAM, TY_STRUCT_CAM_INTRINSIC, &intri_color, sizeof(intri_color)));LOGD("=== Read color calib data");ASSERT_OK(TYGetStruct(hDevice, TY_COMPONENT_RGB_CAM, TY_STRUCT_CAM_CALIB_DATA, &cb_data.color_calib, sizeof(cb_data.color_calib)));//硬ISP功能,仅部分相机的RGB支持硬ISP,如FM854-E1,FM855-E1,TM265和TM421相机。//获取RGB是否支持自动曝光,自动白平衡,自动增益等属性,这些属性虽然不能保存到storage里面,但是默认是开启的。//*********************这几个属性可以默认启用,可以不设置************************** bool hasAUTOEXPOSURE, hasAUTOGAIN, hasAUTOAWB;ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_RGB_CAM, TY_BOOL_AUTO_EXPOSURE, &hasAUTOEXPOSURE));ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_RGB_CAM, TY_BOOL_AUTO_AWB, &hasAUTOAWB));ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_RGB_CAM, TY_BOOL_AUTO_GAIN, &hasAUTOGAIN));if (hasAUTOEXPOSURE && setParameters){ASSERT_OK(TYSetBool(hDevice, TY_COMPONENT_RGB_CAM, TY_BOOL_AUTO_EXPOSURE, true));//turn on AEC 打开自动曝光}if (hasAUTOAWB && setParameters){ASSERT_OK(TYSetBool(hDevice, TY_COMPONENT_RGB_CAM, TY_BOOL_AUTO_AWB, true));//turn on AWB 打开白平衡}if (hasAUTOGAIN && setParameters){ASSERT_OK(TYSetBool(hDevice, TY_COMPONENT_RGB_CAM, TY_BOOL_AUTO_GAIN, true));//turn on AGC,自动增益,仅TM265相机支持该属性}//*********************这几个属性可默认启用,可以不设置************************** //获取RGB支持的属性//*********************这几个属性可以保存到storage里面,可以不设置**************************bool hasRGB_ANALOG_GAIN, hasRGB_R_GAIN, hasRGB_G_GAIN, hasRGB_B_GAIN, hasRGB_EXPOSURE_TIME , hasRGB_AE_TARGET_V;;ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_ANALOG_GAIN, &hasRGB_ANALOG_GAIN));ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_R_GAIN, &hasRGB_R_GAIN));ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_G_GAIN, &hasRGB_G_GAIN));ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_B_GAIN, &hasRGB_B_GAIN));ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_EXPOSURE_TIME, &hasRGB_EXPOSURE_TIME));if (hasRGB_ANALOG_GAIN && setParameters){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_ANALOG_GAIN, 2));//设置RGB模拟增益,仅FM854和FM855等双目相机支持}if (hasRGB_R_GAIN && setParameters){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_R_GAIN, 130));//设置RGB数字增益R通道}if (hasRGB_G_GAIN && setParameters){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_G_GAIN, 80));//设置RGB数字增益G通道}if (hasRGB_B_GAIN && setParameters){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_B_GAIN, 150));//设置RGB数字增益B通道}if (hasRGB_EXPOSURE_TIME && setParameters){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_EXPOSURE_TIME, 300));//设置RGB曝光时间,所有带RGB的相机都支持该属性,只是范围不同}//*********************这几个属性可以保存到storage里面,可以不设置**************************ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_AE_TARGET_V, &hasRGB_AE_TARGET_V));if (hasRGB_AE_TARGET_V && setParameters){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_RGB_CAM, TY_INT_AE_TARGET_V, 3500));//设置RGB自动曝光目标亮度,范围(0,4000)}//使能深度相机//try to enable depth camLOGD("=== Configure components, open depth cam");int32_t componentIDs = TY_COMPONENT_DEPTH_CAM;ASSERT_OK( TYEnableComponents(hDevice, componentIDs) );//设置深度图分辨率if (setParameters){LOGD("=== Configure feature, set depth resolution");//方法一:直接设置分辨率//ASSERT_OK(TYSetEnum(hDevice, TY_COMPONENT_DEPTH_CAM, TY_ENUM_IMAGE_MODE, TY_IMAGE_MODE_DEPTH16_640x480))//方法二:通过枚举相机支持的图像模式,结合图像宽度选定分辨率,不关注具体分辨率if (TY_COMPONENT_DEPTH_CAM){std::vector<TY_ENUM_ENTRY> image_mode_list;TY_STATUS status = TY_STATUS_OK;status = get_feature_enum_list(hDevice, TY_COMPONENT_DEPTH_CAM, TY_ENUM_IMAGE_MODE, image_mode_list);for (int idx = 0; idx < image_mode_list.size(); idx++) {TY_ENUM_ENTRY &entry = image_mode_list[idx];//try to select a resolutionif (TYImageWidth(entry.value) == 640) {LOGD("Select Depth Image Mode: %s", entry.description);int err = TYSetEnum(hDevice, TY_COMPONENT_DEPTH_CAM, TY_ENUM_IMAGE_MODE, entry.value);ASSERT(err == TY_STATUS_OK || err == TY_STATUS_NOT_PERMITTED);status = TYEnableComponents(hDevice, TY_COMPONENT_DEPTH_CAM);break;}}}}//读取深度相机内参和深度相机标定数据//TY_STRUCT_CAM_CALIB_DATA内参是相机最大分辨率的内参//TY_STRUCT_CAM_INTRINSIC内参是相机当前分辨率的内参LOGD("=== Get depth intrinsic");ASSERT_OK(TYGetStruct(hDevice, TY_COMPONENT_DEPTH_CAM, TY_STRUCT_CAM_INTRINSIC, &intri_depth, sizeof(intri_depth)));LOGD("=== Read depth calib data");ASSERT_OK(TYGetStruct(hDevice, TY_COMPONENT_DEPTH_CAM, TY_STRUCT_CAM_CALIB_DATA, &cb_data.depth_calib, sizeof(cb_data.depth_calib)));//you can set TOF camera feature here 下面是TOF相机属性设置//************************************************* ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_DEPTH_CAM, TY_STRUCT_CAM_DISTORTION, &isTof));//判断是否为Tof相机if (isTof && setParameters) {//*********************这些属性可以保存到storage**************************** //设置频段,多相机模式下可设置不同频道int channel = 0;//频段0,1,2,3等LOGD("Set TOF_CHANNEL %d", channel);ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_TOF_CHANNEL, channel));//设置图像质量模式int quality = 2;//质量模式:1,2,4,TM26X只有Basic和mediu模式,而TL430/TM421相机有medium和high模式LOGD("Set DEPTH_QUALITY %d", quality);ASSERT_OK(TYSetEnum(hDevice, TY_COMPONENT_DEPTH_CAM, TY_ENUM_DEPTH_QUALITY, quality));//设置强度置信度阈值int modulation = 640; //强度置信度过滤,小于此阈值的像素点不参与计算深度,即像素点的深度值赋值为 0,,范围(0.65535)LOGD("Set TOF_MODULATION_THRESHOLD %d", modulation);ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_TOF_MODULATION_THRESHOLD, modulation));//设置飞点滤波阈值int filter = 0;//飞点滤波,滤波阈值设置越小,过滤的飞点越多LOGD("Set FILTER_THRESHOLD %d", filter);ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_FILTER_THRESHOLD, filter));bool hasJITTER_THRESHOLD = true;//设置抖动过滤阈值ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_TOF_JITTER_THRESHOLD, &hasJITTER_THRESHOLD));if (hasJITTER_THRESHOLD && setParameters){int jitter = 6;//(1,10),阈值设置值越大,深度图边缘抖动的深度数据过滤得越少,拍摄黑色等低反材质,建议增大该值LOGD("Set TOF_JITTER_THRESHOLD %d", jitter);ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_TOF_JITTER_THRESHOLD, jitter));}滤波设置//set TY_INT_MAX_SPECKLE_SIZE bool hasMAX_SPECKLE_SIZE = true;ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_MAX_SPECKLE_SIZE, &hasMAX_SPECKLE_SIZE));if (hasMAX_SPECKLE_SIZE && setParameters){int speckle_size = 50; //(0,200) //噪点面积小于该值将被过滤LOGD("Set MAX_SPECKLE_SIZE %d", speckle_size);ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_MAX_SPECKLE_SIZE, speckle_size));}//set TY_INT_MAX_SPECKLE_DIFF bool hasMAX_SPECKLE_DIFF = true;ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_MAX_SPECKLE_DIFF, &hasMAX_SPECKLE_DIFF));if (hasMAX_SPECKLE_DIFF && setParameters){int speckle_diff = 200; //(100,500) //相邻像素视差大于该值将被视为噪点LOGD("Set MAX_SPECKLE_DIFF %d", speckle_diff);ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_MAX_SPECKLE_DIFF, speckle_diff));}//*********************这些属性可以保存到storage**************************** // Set TY_BOOL_TOF_ANTI_INTERFERENCE 比如排除3m以外干扰物影响,优先调整anti-inference,只有TM26X相机有该属性bool hasANTI_INTERFERENCE = true;ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_DEPTH_CAM, TY_BOOL_TOF_ANTI_INTERFERENCE, &hasANTI_INTERFERENCE));if (hasANTI_INTERFERENCE && setParameters){LOGD("Set TY_BOOL_TOF_ANTI_INTERFERENCE ");ASSERT_OK(TYSetBool(hDevice, TY_COMPONENT_DEPTH_CAM, TY_BOOL_TOF_ANTI_INTERFERENCE, true));}}//********************只有双目相机拥有下面属性******************************//设置左右IR的模拟增益,数字增益和曝光//adjust the gain and exposure of Left&Right IR camera//获取左右IR支持的属性bool hasIR_ANALOG_GAIN, hasIR_GAIN, hasIR_EXPOSURE_TIME, hasIR_HDR;ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_IR_CAM_LEFT, TY_INT_ANALOG_GAIN, &hasIR_ANALOG_GAIN));ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_IR_CAM_LEFT, TY_INT_GAIN, &hasIR_GAIN));ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_IR_CAM_LEFT, TY_INT_EXPOSURE_TIME, &hasIR_EXPOSURE_TIME));ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_IR_CAM_LEFT, TY_BOOL_HDR, &hasIR_HDR));if (hasIR_ANALOG_GAIN && setParameters){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_IR_CAM_LEFT, TY_INT_ANALOG_GAIN, 2));//设置左右IR模拟增益if (!isTof){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_IR_CAM_RIGHT, TY_INT_ANALOG_GAIN, 2));}}if (hasIR_GAIN && setParameters){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_IR_CAM_LEFT, TY_INT_GAIN, 32));//设置左右IR数字增益if (!isTof){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_IR_CAM_RIGHT, TY_INT_GAIN, 32));}}if (hasIR_EXPOSURE_TIME && setParameters){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_IR_CAM_LEFT, TY_INT_EXPOSURE_TIME, 500)); //设置IR曝光时间if (!isTof){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_IR_CAM_RIGHT, TY_INT_EXPOSURE_TIME, 500));}}if (hasIR_HDR && setParameters){ASSERT_OK(TYSetBool(hDevice, TY_COMPONENT_IR_CAM_LEFT, TY_BOOL_HDR, true));ASSERT_OK(TYSetBool(hDevice, TY_COMPONENT_IR_CAM_RIGHT, TY_BOOL_HDR, true));//设置开启HDR功能}//设置激光器亮度,默认不用设置,除非深度图过曝//adjust the laser powerbool hasLASER_POWER;ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_DEVICE, TY_INT_LASER_POWER, &hasLASER_POWER));if (hasLASER_POWER && setParameters){ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_LASER, TY_INT_LASER_POWER, 100));// range(0,100)}// ********************只有双目相机拥有下面属性******************************//获取所需Buffer大小LOGD("=== Prepare image buffer");uint32_t frameSize;ASSERT_OK( TYGetFrameBufferSize(hDevice, &frameSize) );LOGD("- Get size of framebuffer, %d", frameSize);//分配两个Buffer,并压入队列LOGD(" - Allocate & enqueue buffers");char* frameBuffer[2];frameBuffer[0] = new char[frameSize];frameBuffer[1] = new char[frameSize];LOGD(" - Enqueue buffer (%p, %d)", frameBuffer[0], frameSize);ASSERT_OK( TYEnqueueBuffer(hDevice, frameBuffer[0], frameSize) );LOGD(" - Enqueue buffer (%p, %d)", frameBuffer[1], frameSize);ASSERT_OK( TYEnqueueBuffer(hDevice, frameBuffer[1], frameSize) );//注册事件回调,相机掉线捕获bool device_offline = false;LOGD("Register event callback");ASSERT_OK(TYRegisterEventCallback(hDevice, eventCallback, &device_offline));//触发模式设置bool hasTrigger;ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_DEVICE, TY_STRUCT_TRIGGER_PARAM, &hasTrigger));if (hasTrigger) {TY_TRIGGER_PARAM trigger;//LOGD("Disable trigger mode");//trigger.mode = TY_TRIGGER_MODE_OFF;//连续采集模式 LOGD("=== enable trigger mode");trigger.mode = TY_TRIGGER_MODE_SLAVE;//软触发和硬触发模式ASSERT_OK(TYSetStruct(hDevice, TY_COMPONENT_DEVICE, TY_STRUCT_TRIGGER_PARAM, &trigger, sizeof(trigger)));bool hasDI0_WORKMODE;ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_DEVICE, TY_STRUCT_DI0_WORKMODE, &hasDI0_WORKMODE));//if (hasDI0_WORKMODE)//{// //硬触发模式防抖// TY_DI_WORKMODE di_wm;// di_wm.mode = TY_DI_PE_INT;// di_wm.int_act = TY_DI_INT_TRIG_CAP;// uint32_t time_hw = 10;//单位ms,硬件滤波,小于设定时间的电平信号会被过滤// uint32_t time_sw = 200;//单位ms,软件滤波,连续高频触发情形,小于设置周期的后一个触发信号将被过滤// di_wm.reserved[0] = time_hw | (time_sw << 16);// ASSERT_OK(TYSetStruct(hDevice, TY_COMPONENT_DEVICE, TY_STRUCT_DI0_WORKMODE, &di_wm, sizeof(di_wm)));//}// }//网口相机,启用丢包重传功能//for network onlyLOGD("=== resend: %d", resend);if (resend) {bool hasResend;ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_DEVICE, TY_BOOL_GVSP_RESEND, &hasResend));if (hasResend) {LOGD("=== Open resend");ASSERT_OK(TYSetBool(hDevice, TY_COMPONENT_DEVICE, TY_BOOL_GVSP_RESEND, true));}else {LOGD("=== Not support feature TY_BOOL_GVSP_RESEND");}}//开始采集LOGD("=== Start capture");ASSERT_OK( TYStartCapture(hDevice) );//回调数据初始化cb_data.index = 0;cb_data.hDevice = hDevice;cb_data.saveOneFramePoint3d = false;cb_data.fileIndex = 0;cb_data.intri_depth = &intri_depth;cb_data.intri_color = &intri_color;float scale_unit = 1.;TYGetFloat(hDevice, TY_COMPONENT_DEPTH_CAM, TY_FLOAT_SCALE_UNIT, &scale_unit);cb_data.scale_unit = scale_unit;cb_data.isTof = isTof;//循环取图LOGD("=== While loop to fetch frame");TY_FRAME_DATA frame;bool exit_main = false;int index = 0;while(!exit_main){int key = cv::waitKey(1);switch(key & 0xff){case 0xff:break;case 'q':exit_main = true;break;case 's':cb_data.saveOneFramePoint3d = true;//图片显示窗口上按s键则存一张点云图break;default:LOGD("Pressed key %d", key);}auto timeTrigger = std::chrono::steady_clock::now();//发送一次软触发while (TY_STATUS_BUSY == TYSendSoftTrigger(hDevice));//获取帧,默认超时设置为10sint err = TYFetchFrame(hDevice, &frame, 10000);//获取图像时间戳代码LOGD("=== Time Stamp (%" PRIu64 ")", frame.image[0].timestamp);time_t tick = (time_t)(frame.image[0].timestamp / 1000000);struct tm tm;char s[100];tm = *localtime(&tick);strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", &tm);int milliseconds = (int)((frame.image[0].timestamp % 1000000) / 1000);char ms_str[5];sprintf(ms_str, ".%d", milliseconds);strcat(s, ms_str);LOGD("===Time Stamp %d:%s\n", (int)tick, s);if (device_offline){LOGI("Found device offline");break;}if( err != TY_STATUS_OK ){LOGD("... Drop one frame");continue;}if (err == TY_STATUS_OK) {LOGD("Get frame %d", ++index);int fps = get_fps();if (fps > 0) {LOGI("***************************fps: %d", fps);}}frameHandler(&frame, &cb_data);auto timeGetFrame = std::chrono::steady_clock::now();auto duration = std::chrono::duration_cast<std::chrono::microseconds>(timeGetFrame - timeTrigger);LOGI("*******FetchFrame spend Time : %lld", duration);}ASSERT_OK( TYStopCapture(hDevice) );ASSERT_OK( TYCloseDevice(hDevice) );ASSERT_OK( TYCloseInterface(hIface) );ASSERT_OK( TYDeinitLib() );delete frameBuffer[0];delete frameBuffer[1];LOGD("=== Main done!");return 0;
}
相关文章:
图漾官网Sample_V1版本C++语言完整参考例子---单相机版本
文章目录 1.参考例子 主要梳理了图漾官网Sample_V1版本的例子 1.参考例子 主要增加了从storage区域读取相机参数的设置,使用图漾PercipioViewer软件,如何将相机参数保存到srorage区,可参考链接:保存相机参数操作 保存参数设置 注…...
SSM书籍管理(业务编写)
查询书籍功能 编写Controller类 Controller RequestMapping("/book") public class BookController {//controller调用service层AutowiredQualifier("BookServiceImpl")private BookService bookService;//查询全部的书籍,并且返回到书籍展示…...
kafka消息的顺序性如何保持一致的
目录 背景: 原理: 情况一:如果只有一个分区 情况二:如果有多个分区 总结 背景: 最近面试总是被问这个问题,然后总感觉答得不好就写博客总结一下,可以先看总结 原理: Kafka 中&#…...
在Java中基于Geotools对PostGIS数据库的空间查询实践
目录 前言 一、相关技术背景介绍 1、评价对象AOI 2、数据处理流程 二、对AOI空间范围查询实践 1、空间查询构建 2、空间样式创建 3、成果出图 三、总结 前言 在当今数字化浪潮下,空间数据的应用价值日益凸显,从城市规划到环境监测,从…...
生活需要一些思考
总分总 写文章、做事情、写邮件、写信,都是要【总分总】。 先总【因为没人有耐心一上来就看细节,先总结,别人感兴趣才会看分】 然后分【分中包括多个子部分,或子章节、子目标,他们之间层层递进,最终引出最…...
Scrapy框架之CrawlSpider爬虫 实战 详解
CrawlSpider 是 Scrapy 框架中一个非常实用的爬虫基类,它继承自 Spider 类,主要用于实现基于规则的网页爬取。相较于普通的 Spider 类,CrawlSpider 可以根据预定义的规则自动跟进页面中的链接,从而实现更高效、更灵活的爬取。 Scr…...
DeepSeek主动学习系统:低质量数据炼金术的工程化实践
文章目录 一、技术体系架构升级1.1 四层协同系统架构1.2 关键技术组件解析(1) 跨模态特征对齐引擎(2) 动态采样策略库 二、低质量数据治理全流程2.1 数据清洗与增强流水线2.2 主动学习迭代流程 三、工业级部署方案3.1 分布式计算架构3.2 动态环境应对策略(1) 概念漂移检测(2) 持…...
学习记录:DAY20
技术探索之旅:YAML配置,依赖注入、控制反转与Java注解 前言 最近有点懒了,太松懈可不行。为了让自己保持学习的动力,我决定将最近的学习内容整理成博客,目标是让未来的自己也能轻松理解。我会尽量以整体记录的方式呈…...
[AI]browser-use + web-ui 大模型实现自动操作浏览器
[AI]browser-use web-ui 大模型实现自动操作浏览器 介绍 官方地址:https://github.com/browser-use/web-ui browser-use主要作用是将 AI Agent 与浏览器链接起来从而实现由 AI 驱动的浏览器自动化。今天会给大家介绍如何通过browser-use web-ui来搭建并操作browse…...
使用LangChain连接远程Oracle数据库尝试LLM 提供的SQL智能助理
使用LangChain连接远程Oracle数据库尝试LLM 提供的SQL智能助理 为完成此次数据库连接实验,笔者用自己的笔记本电脑搭建了一台linux虚机,安装了oracle 23C,并借助deepseek创建了若干与电商业务有关的表并插入了一些记录。 接着在windows实体…...
训练神经网络的批量标准化(使用 PyTorch)
构建神经网络是一门艺术,而非一个结果固定的过程。你无法预知最终能否得到有效的模型,而且有很多因素可能导致你的机器学习项目失败。 然而,随着时间的推移,您还将学会一套特定的笔触,这将大大提高您成功的几率。 在…...
阿里Qwen3 8款模型全面开源,免费商用,成本仅为 DeepSeek-R1 的三分之一
想要掌握如何将大模型的力量发挥到极致吗?叶梓老师带您深入了解 Llama Factory —— 一款革命性的大模型微调工具(限时免费)。 1小时实战课程,您将学习到如何轻松上手并有效利用 Llama Factory 来微调您的模型,以发挥其…...
Vue常用的修饰符有哪些有什么应用场景(含deep seek讲解)
Vue.js 事件修饰符的功能与具体应用场景 一、事件修饰符 .stop .stop 的主要作用是 阻止事件冒泡,防止事件从子元素传播到父元素。这在处理嵌套组件或多层 DOM 结构时非常有用。 <div click"parentClick">Parent<button click.stop"chi…...
案例分享|20倍提效!水力设备电磁仿真的云端实战
在现代水力设备制造领域,电磁仿真是贯穿设计、研发到故障诊断的核心技术之一。而随着"双碳"目标驱动下清洁能源设备的迭代加速,水轮机、水泵等设备研发的多物理场耦合特性对仿真精度提出前所未有的挑战。传统仿真工具在处理复杂多物理场耦合等…...
ShenNiusModularity项目源码学习(25:ShenNius.Admin.Mvc项目分析-10)
本文学习并分析ShenNiusModularity项目中的留言管理页面、回收站页面。 1、留言管理页面 留言管理页面用于检索、删除系统中的留言数据,该页面对应的文件Index.cshtml位于ShenNius.Admin.Mvc项目的Areas\Cms\Views\Message内。页面使用的控制器类MessageController…...
github使用记录
1. 首次上传本地项目到 GitHub 1.1 准备 GitHub 仓库 登录 GitHub,点击右上角 → New repository输入仓库名称(建议与本地目录同名)选择公开(Public)或私有(Private)不要勾选 "Initiali…...
NFS-网络文件系统
NFS介绍 NFS ( Network File System ) 即网络文件系统 ,它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样NFS的好…...
Andorid车机UI适配,AndroidUI图px的单位,如何适配1920x720,PPI100的屏幕设备
在 Android 开发中,针对 1920720 分辨率、PPI 100 的屏幕设备进行 UI 适配,需要综合考虑 像素密度(PPI)、屏幕尺寸 和 Android 的密度无关像素(dp) 体系。以下是完整的适配方案: 📌 …...
4.2.4 MYSQL的缓存策略
文章目录 4.2.4 MYSQL的缓存策略1. MYSQL缓存方案用来干什么 2. 缓存相关知识1. mysql主从复制2. 为什么需要缓冲层3. 还有哪些类型数据库 3. 那些方式会提升MYSQL读写性能1. mysql读写分离2. 连接池3. 异步连接 4. 缓存方案是怎么解决的1. redis和MYSQL一致性状态分析1. 流程&…...
省科学技术奖申报答辩PPT设计制作美化
自然科学奖、技术发明奖和科技进步奖是科学技术奖励体系中的三大核心奖项 省科学技术奖的含金量极高,主要体现在经济激励、社会认可、创新驱动及资源整合等方面。其价值不仅在于奖金和荣誉,更在于对科研生态的长远影响,国家科学技术奖的敲门…...
基于 ARM 的自动跟拍云台设计
标题:基于 ARM 的自动跟拍云台设计 内容:1.摘要 摘要:随着摄影和监控需求的不断增长,自动跟拍云台的应用越来越广泛。本设计的目的是开发一款基于 ARM 的自动跟拍云台,以实现对目标的精准跟拍。采用 ARM 微控制器作为核心控制单元࿰…...
Linux电源管理(3)_关机和重启的过程
原文:Linux电源管理(3)_Generic PM之重新启动过程 1.前言 在使用计算机的过程中,关机和重启是最先学会的两个操作。同样,这两个操作在Linux中也存在,可以关机和重启。这就是这里要描述的对象。在Linux Ke…...
SQLMesh增量模型实战指南:时间范围分区
引言 在数据工程领域,处理大规模数据集和高频率数据更新是一项挑战。SQLMesh作为一款强大的数据编排工具,提供了增量模型功能,帮助数据工程师高效地管理和更新数据。本文将详细介绍如何使用SQLMesh创建和管理基于时间范围的增量模型…...
LeetCode -160.相交链表
题目 160. 相交链表 - 力扣(LeetCode) 解法一 哈希表 哈希表解决方案的思路 这个使用哈希表(unordered_set)的解决方案基于一个简单的观察:如果两个链表相交,那么相交点及之后的所有节点都是两个链表共…...
针对Linux挂载NAS供Minio使用及数据恢复的需求
针对Linux挂载NAS供Minio使用及数据恢复的需求,设计以下分阶段解决方案: 一、存储架构设计 存储拓扑 [Minio Server] --> [NAS挂载点 (/mnt/nas/minio-data)] --> [企业级NAS设备]│└─[备份服务器/存储] (可选异地备份)组件版本要求 Minio版本&a…...
【大厂实战】API网关进化史:从统一入口到智能AB分流,如何构建灰度无感知系统?
【大厂实战】API网关进化史:从统一入口到智能AB分流,如何构建灰度无感知系统? 1. 为什么API网关是AB面架构的天然起点? 在分布式微服务架构中,API网关(API Gateway)承担着重要职责:…...
开放平台架构方案- GraphQL 详细解释
GraphQL 详细解释 GraphQL 是一种用于 API 的查询语言,由 Facebook 开发并开源,旨在提供一种更高效、灵活且强大的数据获取和操作方式。它与传统的 REST API 有显著不同,通过类型系统和灵活的查询能力,解决了 REST 中常见的过度获…...
使用 TypeScript 开发并发布一个 npm 包(完整指南)
本教程将一步步教你从零开发、打包并发布一个 TypeScript 工具库到 npm。以日期时间格式化工具为例,涵盖项目初始化、Vite 打包、类型声明输出、npm 配置、实际发布等完整流程,适合开发者直接套用。 文章目录 📁 项目结构预览🧱 初…...
在Anolis OS 8上部署Elasticsearch 7.16.1与JDK 11的完整指南
目录 1. 环境与版本选择 1.1 操作系统选择:Anolis OS 8 1.2 版本匹配说明 1.3 前置条件检查 2. JDK 11安装与配置 2.1 安装流程 2.2 配置详解 3. Elasticsearch 7.16.1安装与优化 3.1 基础安装 3.2 目录规划与权限 3.3 核心配置文件详解 3.4 JVM调优 4. 用户权限管…...
SELinux 从理论到实践:深入解析与实战指南
文章目录 引言:为什么需要 SELinux?第一部分:SELinux 核心理论1.1 SELinux 的三大核心模型1.2 安全上下文(Security Context)1.3 策略语言与模块化 第二部分:实战操作指南2.1 SELinux 状态管理2.2 文件上下…...
巧用 `unittest.mock` 模块实现依赖服务隔离测试
巧用 unittest.mock 模块实现依赖服务隔离测试 引言 在软件开发过程中,单元测试是保障代码质量的核心手段。然而,许多代码依赖于外部服务,如数据库、API 或文件系统,直接进行测试可能会导致: 环境不可控:测试数据可能变化,影响测试结果的稳定性。执行时间长:依赖外部…...
水利三维可视化平台怎么做?快速上手的3步指南
分享大纲: 1、了解水利三维可视化平台 2、选择合适的开发平台 3、快速搭建水利三维可视化平台 第一步:了解水利三维可视化平台 水利三维可视化平台是利用大数据、物联网、数字孪生等技术,将物理实体数字化建模,并通过三维可视化技…...
【DB2】逻辑导出导入注意事项
DB2异构操作系统之间迁移需选择逻辑备份恢复 导出环节 1、设置字符集,源端创建导出目录,并导出数据库DDL db2set db2codepage1208 db2stop force db2start db2look -d YS-e -l -o -createdb db2look_YS.sql导出文件:db2look_YS.sql –详细参数请参考…...
Fiddler抓取APP端,HTTPS报错全解析及解决方案(一篇解决常见问题)
环境:雷电模拟器Android9系统 你所遇到的fiddler中抓取HTTPS的问题可以分为三类:一类是你自己证书安装上逻辑错误,另一种是APP中使用了“证书固定”的手段。三类fiddler中生成证书时的参数过程。 1.Fiddler证书安装上的逻辑错误 更新Opt…...
C语言教程(二十三):C 语言强制类型转换详解
一、强制类型转换的概念 强制类型转换是指在程序中手动将一个数据类型的值转换为另一种数据类型。在某些情况下,编译器可能不会自动进行类型转换,或者自动转换的结果不符合我们的预期,这时就需要使用强制类型转换来明确指定要进行的类型转换。…...
阿里云服务器 篇十二:加入 Project Honey Pot 和使用 http:BL
文章目录 系列文章背景前提条件注册和准备注册安装蜜罐捐赠MX记录(可选)添加 QuickLinks(快速链接)使用 http:BL(HTTP黑名单)获取Access Key(访问秘钥)Apache自动拦截黑名单IP模块Http:BL API文档更多实现案例监控IP空间系列文章 阿里云服务器 篇一:申请和初始化 阿里…...
Android 手动删除 AAR jar 包 中的文件
Duplicate class com.xxxa.naviauto.sdk.listener.OnChangeListener found in modules jetified-xxxa-sdk-v1.1.2-release-runtime (:xxx-sdk-v1.1.2-release:) and jetified-xxxb-sdk-1.1.3-runtime (:xxxb-sdk-1.1.3:) A.aar B.aar 有类冲突; 使用 exclude 排除本地aar无效…...
Tomcat 部署配置指南
## 1. 环境要求 - JDK 8 或更高版本 - Tomcat 8.5/9.x/10.x - Windows 操作系统 ## 2. 安装步骤 ### 2.1 安装JDK 1. 下载并安装JDK 2. 配置环境变量: - JAVA_HOME: JDK安装目录 - Path: 添加 %JAVA_HOME%\bin 3. 验证安装:打开命令提示符&#…...
阿里千问Qwen3技术解析与部署指南 :混合推理架构突破性优势与对DeepSeek R1的全面超越
阿里千问Qwen3技术解析:突破性优势与对DeepSeek R1的全面超越 在2025年4月29日,阿里巴巴发布了新一代开源大模型Qwen3(通义千问3),凭借其创新架构与显著性能提升,迅速成为全球开源AI领域的焦点。本文将从技…...
宾馆一次性拖鞋很重要,扬州卓韵酒店用品详细介绍其材质与卫生标准
宾馆一次性拖鞋在旅途中很重要。它的卫生情况受大家关注。它的舒适度也受大家关注。扬州卓韵酒店用品在这方面经验丰富。其产品质量优良。下面为你详细介绍宾馆一次性拖鞋。 材质选择目前宾馆一次性拖鞋材质多样。常见的有布质、纸质和塑料的。布质拖鞋相对环保舒适。能给脚部…...
推荐系统中 Label 回收机制之【时间窗口设计】
目录 引言一、业务需求:目标导向的窗口设计1.1 用户行为周期决定窗口基础1.2 业务目标驱动窗口粒度1.3 动态场景下的弹性调整 二、数据特性:窗口设计的底层约束2.1 数据分布与稀疏性适配2.2 数据延迟与完整性保障2.3 特征时效性分层 三、算法模型&#x…...
DevExpressWinForms-XtraMessageBox-使用教程
XtraMessageBox-使用教程 一、基础使用:快速弹出标准消息框 XtraMessageBox 的基础使用非常简单,只需调用XtraMessageBox.Show方法即可弹出一个标准的消息框。根据不同的使用需求,Show方法有多种重载形式。 1.1 仅显示提示信息 当我们仅仅…...
ETL数据集成与数据资产的紧密关联,解锁数据价值新密码
数据已然成为企业最为珍贵的资产之一。无论是传统行业巨头,还是新兴的互联网企业,都在积极挖掘数据背后所蕴含的巨大商业价值。而在这个过程中,ETL(Extract,Transform,Load)作为数据处理的关键环…...
【无报错,亲测有效】如何在Windows和Linux系统中查看MySQL版本
如何在Windows和Linux系统中查看MySQL版本 MySQL作为最流行的开源关系型数据库管理系统之一,了解如何查看其版本信息对于开发者和数据库管理员来说是常用的一个基本操作。本文将详细介绍在Windows和Linux系统中查看MySQL版本的方法。 文章目录 如何在Windows和Linu…...
【Leetcode 每日一题】2962. 统计最大元素出现至少 K 次的子数组
问题背景 给你一个整数数组 n u m s nums nums 和一个 正整数 k k k。 请你统计有多少满足 「 n u m s nums nums 中的 最大 元素」至少出现 k k k 次的子数组,并返回满足这一条件的子数组的数目。 子数组是数组中的一个连续元素序列。 数据约束 1 ≤ n u m s …...
网络爬取需谨慎:警惕迷宫陷阱
一、技术背景:网络爬虫与数据保护的博弈升级 1. 问题根源:AI训练数据爬取的无序性 数据需求爆炸:GPT-4、Gemini等大模型依赖数万亿网页数据训练,但大量爬虫无视网站的robots.txt协议(非法律强制),未经许可抓取内容(如新闻、学术论文、代码),引发版权争议(如OpenAI被…...
‘WebDriver‘ object has no attribute ‘find_element_by_class‘
在使用Selenium进行Web自动化测试时,如果你遇到了错误信息:“‘WebDriver’ object has no attribute ‘find_element_by_class’”,这通常是因为在Selenium 4及以上版本中,find_element_by_* 和 find_elements_by_* 这类方法已经…...
ComfyUI 学习笔记,案例1:2_pass_txt2img
背景 ComfyUI 官方案例学习笔记,本文是跑出的第三个案例,但确是官网案例的第一个,所以运行起来总体比较顺利。整理几点页面使用技巧: 是网页版本,没有 IDEA,而且画布上没有滚动条,想看清楚内容…...
代码颜色模式python
1. CMYK(印刷场景) 例子:某出版社设计书籍封面时,使用 Adobe Illustrator 绘制图案。 红色封面的 CMYK 值可能为:C0, M100, Y100, K0(通过洋红和黄色油墨混合呈现红色)。印刷前需将设计文件转…...
Android第五次面试总结之网络篇(修)
一、域名解析到服务器的过程(DNS 解析流程) 当应用发起网络请求(如https://www.example.com)时,操作系统需先将域名转换为服务器 IP 地址,这一过程通过 DNS(域名系统) 完成…...