qt配合映美精取图开发

  1. 最近开发一个项目,用映美精相机配合halcon做取图开发,由于网上资料小特意写个记录。
  2. 到映美精官网下载驱动,映美精官网,下载映美精的工具开发包SDK 映美精的SDK
  3. 下载SDK后找到classlib文件夹
    请添加图片描述
    里面就是SDK
  4. 新建一个qt程序,引入SDK
    请添加图片描述
  5. 新建一个相机类

头文件

#ifndef CAMERAGRAP_H
#define CAMERAGRAP_H#include <QObject>
#include "QDebug"
#include <tisudshl.h>
#include <algorithm>/***sink监控***/
class SinkListener : public DShowLib::FrameQueueSinkListener
{
public:/***槽链接成功***/void    sinkConnected(DShowLib::FrameQueueSink& sink,const DShowLib::FrameTypeInfo& frameType );/***取到图片是响应***/void framesQueued( DShowLib::FrameQueueSink& sink );/***槽链接断开回调***/void sinkDisconnected(DShowLib::FrameQueueSink& sink );
};class CameraGrap : public QObject
{Q_OBJECT
public:explicit CameraGrap(QObject *parent = nullptr);~CameraGrap();/***初始化***/void Init();/***读取配置***/void ReadConfig();/***保存配置***/bool WriteConfig();/***开始相机***/void StartCamera();/***停止相机***/void StopCamera();/***释放资源***/void ReleaseSource();/***设置相机的触发模式为触发取图***/void SetCameraTriggerTakeImage();/***设置相机试试视频取图***/void SetCameraLiveTakeImage();/***设置相机曝光***/void SetCameraExpource(double expource_);/***设置相机增益***/void SetCameraGain(double gain_);/***触发下相机取图***/void TriggerCameraTakeImage();// /***槽链接成功***/// void    sinkConnected(DShowLib::FrameQueueSink& sink,//                    const DShowLib::FrameTypeInfo& frameType );// /***取到图片是响应***/// void framesQueued( DShowLib::FrameQueueSink& sink );// /***槽链接断开回调***/// void sinkDisconnected(DShowLib::FrameQueueSink& sink );// /***重写取图回调函数***/// void frameReady(DShowLib::Grabber& caller, smart_ptr<DShowLib::MemBuffer> pBuffer, DWORD FrameNumber ) override;// void overlayCallback(DShowLib::Grabber& caller, smart_ptr<DShowLib::OverlayBitmap> pBitmap, const DShowLib::tsMediaSampleDesc& desc );signals:// /***获取图片完成标志***/// void FinallyGetImage();
public:static CameraGrap _camer_grap;/***相机名称***/QString _camera_name;/***相机视频的格式***/QString _camera_video_format;/***相机曝光***/double _camera_expource;/***相机增益***/double _camera_gain;/***相机抗干扰数***/double _camera_noise_suppression;/***相机有无标志***/bool _camera_exist;/***创建一个抓拍,一定创建成指针形式,不然会跟***/DShowLib::Grabber* _grabber;// /***sink监控***/SinkListener _listener_instance;// DShowLib::FrameTypeInfoArray _accepted_types;/***接受图片的格式***/DShowLib::FrameTypeInfo _accepted_type;/***槽***/DShowLib::tFrameQueueSinkPtr _psink;
};#endif // CAMERAGRAP_H

内容文件

#include "cameragrap.h"
#include <DeeplearnInspection/deeplearninspection.h>
#include <QCoreApplication>
#include "xlsxdocument.h"
#include "QMetaMethod"
// #include "ic4-interop/interop-HALCON.h"CameraGrap CameraGrap::_camer_grap;void SinkListener::sinkConnected(DShowLib::FrameQueueSink& sink,const DShowLib::FrameTypeInfo& frameType )
{UNREFERENCED_PARAMETER( frameType );/***链接成功分配内存***/sink.allocAndQueueBuffers(1);
}void SinkListener::framesQueued(DShowLib::FrameQueueSink& sink)
{DShowLib::tFrameQueueBufferPtr buffer = sink.popOutputQueueBuffer();//unsigned int frame_number = buffer->getFrameMetaData().mediaSampleDesc.FrameNumber;// DShowLib::tColorformatEnum format_= buffer->getFrameType().getColorformat();int width_=buffer->getFrameType().dim.cx;int height_=buffer->getFrameType().dim.cy;// HalconCpp::GenImageInterleaved(&ho_Image, (void*)pBuffer, "rgb", width, height, 0, "byte", width * 3, height, 0, 0);HalconCpp::HTuple hptr_=(Hlong)buffer->getPtr();HalconCpp::GenImage1(&DeeplearnInspection::_deeplearn_inspection._image,"byte",width_,height_,hptr_);DeeplearnInspection::_deeplearn_inspection._image_exist=true;hptr_.Clear();/***释放内存资源***/buffer.destroy();int size_input_= sink.getInputQueueSize();int size_output_=sink.getOutputQueueSize();sink.popAllOutputQueueBuffers().clear();sink.popAllInputQueueBuffers().clear();/***重新分配内存资源***/sink.allocAndQueueBuffers(1);size_input_= sink.getInputQueueSize();size_output_=sink.getOutputQueueSize();/***触发相机取图完成***/DeeplearnInspection::_deeplearn_inspection.TriggerCameraImageWriteFinally();
}void SinkListener::sinkDisconnected(DShowLib::FrameQueueSink& sink)
{;
}CameraGrap::CameraGrap(QObject *parent): QObject{parent}
{
}CameraGrap::~CameraGrap()
{
}void CameraGrap::Init()
{/***读取配置***/ReadConfig();/***初始化相机底层***/DShowLib::InitLibrary();/***创建一个抓拍***/_grabber=new DShowLib::Grabber();/***获取相机驱动***/auto cameras_= _grabber->getAvailableVideoCaptureDevices();/***判断有没有相机***/int camera_count_= cameras_->size();if(camera_count_>0){for(int i=0;i<camera_count_;i++){/***获取相机名称***/std::string camera_name_;camera_name_=cameras_->at(i).getName();if(camera_name_==_camera_name.toStdString()){i=camera_count_;if(_grabber->openDev(camera_name_)){//_grabber->showVCDPropertyPage();/***设置图片格式***/// _grabber->setVideoFormat("Y800 (1424x712)");DShowLib::dstringa video_format_=_camera_video_format.toStdString();_grabber->setVideoFormat(video_format_);/***设置外部出发***/_grabber->setExternalTrigger(1);/***给如抗误触发参数***/DShowLib::tIVCDAbsoluteValuePropertyPtr noise_suppression_time_ = _grabber->getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>(DShowLib::VCDID_Trigger, DShowLib::VCDElement_TriggerNoiseSuppressionTime);if(noise_suppression_time_==NULL){qDebug() << "noise suppression time auto is failed";}else{long max_=noise_suppression_time_->getRangeMax();long min_=noise_suppression_time_->getRangeMin();long cvalue_;cvalue_=noise_suppression_time_->getValue();qDebug() << "noise suppression time is "+QString::number(cvalue_);if((max_>=_camera_noise_suppression)&&(min_<=_camera_noise_suppression)){noise_suppression_time_->setValue(_camera_noise_suppression);}else{noise_suppression_time_->setValue(min_);}}/***设置帧率***/_grabber->setFPS(120);// Enable the overlay bitmap to display the frame counter in the live video._grabber->setOverlayBitmapPathPosition( DShowLib::ePP_DEVICE );_grabber->getOverlay(DShowLib::ePP_DEVICE )->setEnable( true );// Create a FrameTypeInfoArray data structure describing the allowed color formats.//_accepted_types= DShowLib::FrameTypeInfoArray::createStandardTypesArray();/***设置槽接受图片的格式***/_accepted_type =DShowLib::eY800;// Create the frame sink_psink= DShowLib::FrameQueueSink::create(this->_listener_instance, _accepted_type);// Apply the sink to the grabber._grabber->setSinkType(_psink);/***设置曝光手动***/DShowLib::tIVCDSwitchPropertyPtr exposure_auto = _grabber->getVCDPropertyInterface<DShowLib::IVCDSwitchProperty>( DShowLib::VCDID_Exposure, DShowLib::VCDElement_Auto);if( exposure_auto == NULL ){qDebug() << "exposure auto is failed";}else{exposure_auto->setSwitch(false);}/***获取曝光的范围,设置相机曝光***/DShowLib::tIVCDRangePropertyPtr exposure_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Exposure, DShowLib::VCDElement_Value);if( exposure_range == NULL ){qDebug() << "exposure auto is failed";}else{// std::cout << "Current Exposure range value: " << exposure_range->getValue() << std::endl;// std::cout << "Exposure range range: [" << exposure_range->getRangeMin() << ".." << exposure_range->getRangeMax() << "]" << std::endl;long max_=exposure_range->getRangeMax();long min_=exposure_range->getRangeMin();long cvalue_;cvalue_=exposure_range->getValue();qDebug() << "expource is "+QString::number(cvalue_);if((max_>=_camera_expource)&&(min_<=_camera_expource)){exposure_range->setValue(_camera_expource);}else{exposure_range->setValue(min_);}}// /***确认曝光是否设置成功***/// DShowLib::tIVCDAbsoluteValuePropertyPtr exposure_absolute = _grabber.getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>( DShowLib::VCDID_Exposure,DShowLib::VCDElement_Value);// if( exposure_absolute == NULL )// {//     qDebug() << "vilation is failed";// }// else// {//     long exposure_= exposure_absolute->getValue();//     qDebug() << "expource is "+QString::number(exposure_);// }/***设置增益手动***/DShowLib::tIVCDSwitchPropertyPtr gain_auto = _grabber->getVCDPropertyInterface<DShowLib::IVCDSwitchProperty>( DShowLib::VCDID_Gain, DShowLib::VCDElement_Auto);if( gain_auto == NULL ){qDebug() << "exposure auto is failed";}else{gain_auto->setSwitch(false);}/***获取增益范围,设置增益***/DShowLib::tIVCDRangePropertyPtr gain_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Gain, DShowLib::VCDElement_Value);if( gain_range == NULL ){qDebug() << "exposure auto is failed";}else{long max_=gain_range->getRangeMax();long min_=gain_range->getRangeMin();long cvalue_;cvalue_=gain_range->getValue();if((max_>=_camera_gain)&&(min_<=_camera_gain)){gain_range->setValue(_camera_gain);}else{gain_range->setValue(min_);}}// /***确认曝光是否设置成功***/// DShowLib::tIVCDAbsoluteValuePropertyPtr gain_absolute = _grabber.getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>( DShowLib::VCDID_Gain,DShowLib::VCDElement_Value);// if( gain_absolute == NULL )// {//     qDebug() << "vilation is failed";// }// else// {//     long gain_= gain_absolute->getValue();//     qDebug() << "gain is "+QString::number(gain_);// }_camera_exist=true;}}}}else{_camera_exist=false;qDebug() << "no found devices";}
}void CameraGrap::ReadConfig()
{QString config_path_=QCoreApplication::applicationDirPath()+"/CameraConfig.xlsx";QFile file_(config_path_);if(file_.exists()){QXlsx::Document xlsx_(config_path_);if(xlsx_.load()){int row_count_=xlsx_.dimension().rowCount();int column_count_=xlsx_.dimension().columnCount();if((row_count_>4)&&(column_count_>1)){_camera_name= xlsx_.cellAt(2,2)->value().toString();_camera_expource=xlsx_.cellAt(3,2)->value().toDouble();_camera_gain=xlsx_.cellAt(4,2)->value().toDouble();_camera_video_format=xlsx_.cellAt(5,2)->value().toString();_camera_noise_suppression=xlsx_.cellAt(6,2)->value().toDouble();}else{qDebug() << "Failed to load CameraConfig.xlsx file.";}}}else{qDebug() << "CameraConfig.xlsx file is not exist";}file_.close();
}bool CameraGrap::WriteConfig()
{bool ok_=false;QString config_path_=QCoreApplication::applicationDirPath()+"/CameraConfig.xlsx";QXlsx::Document xlsx_;/***写入抬头***/xlsx_.write(1,1,"名称");xlsx_.write(1,2,"值");xlsx_.write(2,1,"CameraName");xlsx_.write(2,2,_camera_name);xlsx_.write(3,1,"Expource");xlsx_.write(3,2,QString::number(_camera_expource));xlsx_.write(4,1,"Gain");xlsx_.write(4,2,QString::number(_camera_gain));xlsx_.write(5,1,"VideoFormat");xlsx_.write(5,2,_camera_video_format);xlsx_.write(6,1,"NoiseSuppression");xlsx_.write(6,2,_camera_noise_suppression);if(!xlsx_.saveAs(config_path_)){qDebug() << "save the DataCache.xlsx failed";}else{ok_=true;}return ok_;
}void CameraGrap::StartCamera()
{if(_camera_exist==true){_grabber->startLive(false);}
}void CameraGrap::StopCamera()
{if(_camera_exist==true){_grabber->stopLive();}
}void CameraGrap::ReleaseSource()
{if(_camera_exist==true){if (_grabber->isDevOpen()){if(_grabber->isLive()){_grabber->stopLive();}_grabber->closeDev();}}delete _grabber;
}void CameraGrap::SetCameraTriggerTakeImage()
{if(_camera_exist==true){/***设置触发模式为软触发***/_grabber->setExternalTrigger(true);}
}void CameraGrap::SetCameraLiveTakeImage()
{if(_camera_exist==true){/***设置相机直播模式***/_grabber->setExternalTrigger(false);}
}void CameraGrap::SetCameraExpource(double expource_)
{if(_camera_exist==true){_camera_expource =expource_;/***获取曝光的范围,设置相机曝光***/DShowLib::tIVCDRangePropertyPtr exposure_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Exposure, DShowLib::VCDElement_Value);if( exposure_range == NULL ){qDebug() << "exposure auto is failed";}else{// std::cout << "Current Exposure range value: " << exposure_range->getValue() << std::endl;// std::cout << "Exposure range range: [" << exposure_range->getRangeMin() << ".." << exposure_range->getRangeMax() << "]" << std::endl;long max_=exposure_range->getRangeMax();long min_=exposure_range->getRangeMin();long cvalue_;cvalue_=exposure_range->getValue();qDebug() << "expource is "+QString::number(cvalue_);if((max_>_camera_expource)&&(min_<_camera_expource)){exposure_range->setValue(_camera_expource);}else{exposure_range->setValue(min_);}}}
}void CameraGrap::SetCameraGain(double gain_)
{if(_camera_exist==true){_camera_gain=gain_;DShowLib::tIVCDRangePropertyPtr gain_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Gain, DShowLib::VCDElement_Value);if( gain_range == NULL ){qDebug() << "exposure auto is failed";}else{long max_=gain_range->getRangeMax();long min_=gain_range->getRangeMin();long cvalue_;cvalue_=gain_range->getValue();if((max_>_camera_gain)&&(min_<_camera_gain)){gain_range->setValue(_camera_gain);}else{gain_range->setValue(min_);}}}
}void CameraGrap::TriggerCameraTakeImage()
{if(_camera_exist==true){DShowLib::tIVCDButtonPropertyPtr btn_= _grabber->getVCDPropertyInterface<DShowLib::IVCDButtonProperty>(DShowLib::VCDID_TriggerMode, DShowLib::VCDElement_SoftwareTrigger);if(btn_==NULL){}else{btn_->push();}}
}// void CameraGrap::frameReady(DShowLib::Grabber& caller,smart_ptr<DShowLib::MemBuffer> pBuffer,DWORD FrameNumber)
// {
//     // int width_=pBuffer->getFrameType().dim.cx;
//     // int height_=pBuffer->getFrameType().dim.cy;//     // uchar* ptr_=static_cast<uchar*>(pBuffer->getPtr());
//     // HalconCpp::HTuple hptr_=(int)ptr_;//     // HalconCpp::GenImage1(&DeeplearnInspection::_deeplearn_inspection._image,
//     //                      "byte",
//     //                      width_,
//     //                      height_,
//     //                      hptr_);
//     // hptr_.Clear();//     // QMetaMethod value_change_signal_=QMetaMethod::fromSignal(&CameraGrap::FinallyGetImage);
//     // if(this->isSignalConnected(value_change_signal_))
//     // {
//     //     emit FinallyGetImage();
//     // }
//     ;
// }// void CameraGrap::overlayCallback(DShowLib::Grabber& caller,
//                                  smart_ptr<DShowLib::OverlayBitmap> pBitmap,
//                                  const DShowLib::tsMediaSampleDesc& desc)
// {// }

6.代码分析
要获取相机的图片,主要创建一个类继承public DShowLib::FrameQueueSinkListener,
然后设置sink,代码如下:
// Create the frame sink
_psink= DShowLib::FrameQueueSink::create(this->_listener_instance, _accepted_type);
// Apply the sink to the grabber.
_grabber->setSinkType(_psink);
在相机取到图片后会回调sink,即回调framesQueued函数,在里面进行转换。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/10201.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

springboot yml文件数据源出现警告/报黄/数据库配置警告问题

1、看一下数据源的依赖是不是都引入完整了 2、看一下数据源是否有拼写错误 上图就是数据源拼写错误

手机上用什么方法可以切换ip

手机上用什么方法可以切换IP&#xff1f;在某些特定情境下&#xff0c;用户可能需要切换手机的IP地址&#xff0c;以满足网络安全、隐私保护或绕过地域限制等需求。下面以华为手机为例&#xff0c;将详细介绍手机IP地址切换的几种方法&#xff0c;帮助用户轻松实现这一目标。 一…

python可视化将多张图整合到一起(画布)

这周有点事忙着&#xff0c;没时间重温刚结束的Mathurcup数学建模&#xff0c;这两天也是再看了下&#xff0c;论文还是赶紧挺烂的&#xff0c;但比国赛又有进步&#xff08;说起国赛又不得不抱怨了&#xff0c;基本其余省份都发了&#xff0c;但江西......哎&#xff09;。哎&…

vue2,vue3,uniapp,小程序实现前端url生成二维码

最近遇到一个项目&#xff0c;api返回url地址&#xff0c;前端通过地址生成二维码。 话不多说直接上代码&#xff0c;亲测有效&#xff0c;希望能帮助大家&#xff0c;同时如果有更好的方法希望大家能够分享 1、第一步&#xff0c;在项目的utils文件夹下面创建一个weapp-qrco…

【韩老师零基础30天学会Java】01章

什么是程序&#xff1f; JavaEE企业版 示例1 public class Test{public static void main(String[] args){int res11;System.out.println("result"res);}}D:\Java\code>javac Test.javaD:\Java\code>java Test 缁撴灉2D:\Java\code>javac Test.javaD:\Java…

华为交换机实现不同VLAN内的互通配置(汇聚层设备作为网关)

背景如下&#xff1a; 如下图所示&#xff0c;PC1和PC2分别属于VLAN 2和VLAN 3&#xff0c;通过接入层设备DeviceB接入汇聚层设备DeviceA。PC3属于VLAN 4&#xff0c;通过接入层设备DeviceC接入汇聚层设备DeviceA。DeviceC不做任何配置&#xff0c;当做HUB即插即用。汇聚层设备…

SpringBoot旅游酒店系统源码免费分享+本地部署及介绍 - 幽络源

初步介绍 这是一套基于SpringBoot的旅游酒店系统&#xff0c;含有前台和后台&#xff0c;需要注意的是图片文件是存放于target中的&#xff0c;因此不建议删除这个临时目录。 原文及源码获取链接 > SpringBoot旅游酒店管理系统免费分享-幽络源 所需环境 JDK1.8、Maven、…

Java开发中的分布式锁使用教程

1. 基于ZooKeeper的分布式锁 1.1 引入依赖 在项目的pom.xml文件中添加以下依赖&#xff1a; <dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>latest</version> </dep…

zynq pl设计中断问题

问题 逻辑工程师vivado工具生成的pl hdf文件后,通过xilinx的工具解析的的dts文件,会出现中断号异常的问题。 原始问题肯定是硬件表现为通讯异常,此处以网口为例,则网口不通。 网口查询 uboot下网口信息 如下命令查询到 两个mac下对应的phy,地址分别为4和6,和硬件设计一…

Scala 的包及其导入

Scala使用包来创建用于模块化程序的命名空间。通过在Scala文件的顶部声明一个或多个包名称可以创建包&#xff0c;另一种声明包的方式是使用0&#xff0c;这种方式可以嵌套包&#xff0c;并且提供更好的范围与封装控制。对于包的导入&#xff0c;Scala与Java的区别之一便是&…

【MySQL】关于MySQL启动后mysqld_safe和mysqld进程

在mysql服务器启动后&#xff0c;有2个进程mysqld_safe和mysqld,这是为啥&#xff1f; # ps -ef | grep mysqld root 6488 3324 0 Sep03 pts/0 00:00:00 /bin/sh /mysqlsoft/mysql/bin/mysqld_safe --defaults-file/etc/my.cnf --usermysql mysql 7327 6488 0 Sep03 pts/0 0…

Rust @绑定(Rust@绑定)(在模式匹配的同时将值绑定到变量)

文章目录 Rust中的绑定基础概念示例&#xff1a;基本模式匹配 绑定的使用示例&#xff1a;范围匹配并绑定变量 深入探索绑定的好处示例&#xff1a;复杂数据结构中的应用 总结 附加 Rust中的绑定 Rust 语言以其强类型系统和内存安全的特性著称。在进行模式匹配时&#xff0c;R…

数据结构-图的概念

不存在空图现象,顶点集不能为空,边集可以为空 研究链接一个顶点的边有多少条非常有意义 无向图的度边的二倍 有向图的入度出度,度边数 有向图一致 重点 子图必须联通,尽可能多的边和结点 对于一个生成树,他有n个节点就有n-1条边 修路问题将各个村庄相连,由于经费有限,只能选择…

黑马程序员Redis学习【持续更新】

Redis基础 一、Redis入门 1.Redis简介 【1】为什么学习Redis Redis是一个基于内存的key-value结构数据库。「Remote Dictionary Service」的首字母缩写&#xff0c;也就是「远程字典服务-remote dictionary server」。 基于内存存储&#xff0c;读写性能高适合存储热点数据…

利用SEO在4个月内打造每月940美元的导航站

在软件开发领域&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;的潜力常常被人们低估&#xff0c;但它却能为网站增长带来显著效果。特别是在AI技术的加持下&#xff0c;你可以极大地加速流量增长并自动化大部分工作。本文将详细介绍一名Reddit用户如何在4个月内&#xf…

字节青训-数字字符串格式化

问题描述 小M在工作时遇到了一个问题&#xff0c;他需要将用户输入的不带千分位逗号的数字字符串转换为带千分位逗号的格式&#xff0c;并且保留小数部分。小M还发现&#xff0c;有时候输入的数字字符串前面会有无用的 0&#xff0c;这些也需要精简掉。请你帮助小M编写程序&…

HER304-ASEMI轴向高效恢复二极管HER304

编辑&#xff1a;ll HER304-ASEMI轴向高效恢复二极管HER304 型号&#xff1a;HER304 品牌&#xff1a;ASEMI 封装&#xff1a;DO-27 特性&#xff1a;轴向高效恢复二极管 正向电流&#xff1a;3A 反向耐压&#xff1a;300V 恢复时间&#xff1a;35ns 引脚数量&#xf…

信息宣传投稿栽跟头不可怕,关键是你要能再站起来

在繁忙的市郊,一家的事业基层单位,这里汇聚了各路英才,每个科室都有自己的专长。然而,有一项任务,让这些精英们头疼不已——单位信息宣传投稿。 起初,大家对这项任务并不以为然,以为不过是小菜一碟。李科长甚至开玩笑说:“不就是写篇文章,投个稿嘛,我们这些笔杆子还怕这个?”…

iMeta | 复杂热图(ComplexHeatmap)可视化文章最新版,画热图就引它

复杂热图可视化 https://doi.org/10.1002/imt2.43 PROTOCOL ●2022年8月&#xff0c;德国癌症研究中心顾祖光在iMeta在线发表了题为“Complex heatmap visualization”的方法类文章。 ● 该研究系统性地介绍了 ComplexHeatmap R包在复杂热图可视化方面的特性和功能。 ● 第…

HTTP的了解

从输入 URL 到页面展示到底发生了什么&#xff1f;&#xff08;非常重要&#xff09; 类似的问题&#xff1a;打开一个网页&#xff0c;整个过程会使用哪些协议&#xff1f; 先来看一张图&#xff08;来源于《图解 HTTP》&#xff09;&#xff1a; 上图有一个错误需要注意&…