点云处理【四】(点云关键点检测)

news2024/11/16 15:27:02

第一章 点云数据采集
第二章 点云滤波
第二章 点云降采样


1.点云关键点是什么?

关键点也称为兴趣点,它是2D图像、3D点云或曲面模型上,可以通过定义检测标准来获取的具有稳定性、区别性的点集。

我们获得的数据量大,特别是几十万个以上的点云,里面有很多冗余数据,会导致处理起来比较耗时。
降采样是一种有效的减少数据、缩减计算量的方法。

2.关键点检测算法(本数据单位为mm,通常数据单位为m,取半径之类得参数要除1000)

2.1 ISS关键点

ISS 关键点通过计算每个点与其近邻点的曲率变化,得到该点的稳定性和自适应尺度,从而提取稳定性和尺度合适的关键点。

Open3d(需要ply格式)

import open3d as o3d
import numpy as np
import time
class o3dtut:
    def get_bunny_mesh():
        mesh = o3d.io.read_triangle_mesh("second_radius_cloud.ply")
        mesh.compute_vertex_normals()
        return mesh
    def keypoints_to_spheres(keypoints):

        spheres = o3d.geometry.TriangleMesh()
        for keypoint in keypoints.points:
         sphere = o3d.geometry.TriangleMesh.create_sphere(radius=10)
         sphere.translate(keypoint)
         spheres += sphere
         spheres.paint_uniform_color([1.0, 0.0, 0.0])
        return spheres


mesh = o3dtut.get_bunny_mesh()
pcd = o3d.geometry.PointCloud()
pcd.points = mesh.vertices
tic = time.time()
keypoints = o3d.geometry.keypoint.compute_iss_keypoints(pcd,
                                                        salient_radius=10,
                                                        non_max_radius=10,
                                                        gamma_21=0.5,
                                                        gamma_32=0.5)
toc = 1000 * (time.time() - tic)
print("ISS Computation took {:.0f} [ms]".format(toc))

mesh.compute_vertex_normals()
mesh.paint_uniform_color([0.0, 0.0, 1.0])
o3d.visualization.draw_geometries([o3dtut.keypoints_to_spheres(keypoints), mesh],window_name="ISS检测",width=800,height=800)

请添加图片描述

PCL

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/keypoints/iss_3d.h>
#include <pcl/visualization/pcl_visualizer.h>

int main(int argc, char** argv)
{
    // 读取点云数据
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
    if (pcl::io::loadPCDFile<pcl::PointXYZ>("second_radius_cloud.pcd", *cloud) == -1)
    {
        PCL_ERROR("Couldn't read the input PCD file \n");
        return (-1);
    }

    // ISS关键点检测参数
    double salient_radius = 10;
    double non_max_radius = 10;
    double gamma_21 = 0.5;
    double gamma_32 = 0.5;
    double min_neighbors = 5;
    int threads = 4;

    // 执行ISS关键点检测
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::ISSKeypoint3D<pcl::PointXYZ, pcl::PointXYZ> iss_detector;
    iss_detector.setSearchMethod(tree);
    iss_detector.setSalientRadius(salient_radius);
    iss_detector.setNonMaxRadius(non_max_radius);
    iss_detector.setThreshold21(gamma_21);
    iss_detector.setThreshold32(gamma_32);
    iss_detector.setMinNeighbors(min_neighbors);
    iss_detector.setNumberOfThreads(threads);
    iss_detector.setInputCloud(cloud);
    iss_detector.compute(*keypoints);

    // 可视化
    pcl::visualization::PCLVisualizer viewer("ISS Keypoints");
    viewer.setBackgroundColor(0, 0, 0);
    viewer.addPointCloud<pcl::PointXYZ>(cloud, "cloud");
    viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "cloud");
    viewer.addPointCloud<pcl::PointXYZ>(keypoints, "keypoints");
    viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "keypoints");
    viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "keypoints");
    while (!viewer.wasStopped())
    {
        viewer.spinOnce(100);
    }

    return 0;
}

请添加图片描述

2.2 Harris关键点

Harris关键点检测通过计算每个点的协方差矩阵,求解特征值和特征向量,来判断该点是否为关键点。如果Harris矩阵的两个特征值都很大,则该点是关键点。具有较好的旋转不变性和尺度不变性。

PCL

#include
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/io/io.h>
#include <pcl/keypoints/harris_3d.h>//harris特征点估计类头文件声明
#include
#include
#include <pcl/console/parse.h>
using namespace std;

int main()
{
pcl::PointCloudpcl::PointXYZ::Ptr input_cloud (new pcl::PointCloudpcl::PointXYZ);
pcl::io::loadPCDFile (“second_radius_cloud.pcd”, *input_cloud);
pcl::PCDWriter writer;
float r_normal=10;//法向量估计的半径
float r_keypoint=40;//关键点估计的近邻搜索半径

typedef pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZI> ColorHandlerT3;

pcl::PointCloud<pcl::PointXYZI>::Ptr Harris_keypoints (new pcl::PointCloud<pcl::PointXYZI> ());//存放最后的特征点提取结果
pcl::HarrisKeypoint3D<pcl::PointXYZ,pcl::PointXYZI,pcl::Normal>* harris_detector = new pcl::HarrisKeypoint3D<pcl::PointXYZ,pcl::PointXYZI,pcl::Normal> ;

harris_detector->setRadius(r_normal);//设置法向量估计的半径
harris_detector->setRadiusSearch(r_keypoint);//设置关键点估计的近邻搜索半径
harris_detector->setInputCloud (input_cloud);//设置输入点云
harris_detector->compute (*Harris_keypoints);//结果存放在Harris_keypoints
pcl::visualization::PCLVisualizer viewer("clouds");
viewer.setBackgroundColor(255,255,255);
viewer.addPointCloud (Harris_keypoints, ColorHandlerT3 (Harris_keypoints, 0.0, 0.0, 255.0), "Harris_keypoints");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,8,"Harris_keypoints");
viewer.addPointCloud(input_cloud,"input_cloud");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,0,0,0,"input_cloud");
viewer.initCameraParameters();
viewer.saveScreenshot("screenshot.png");
viewer.spin ();

}

请添加图片描述

2.3 NAFR关键点

NARF算法是一种基于法向量的点云关键点提取算法。它通过将点云投影到二维图像上,并计算每个像素周围梯度直方图,来寻找具有唯一性和重复性的关键点。

PCL
注意修改角度范围和角度分辨率

#include <iostream>
 #include <pcl/range_image/range_image.h> // 深度图头文件
 #include <pcl/io/pcd_io.h>               // PCD文件读取头
 #include <pcl/visualization/range_image_visualizer.h>// 深度图可视化头
 #include <pcl/visualization/pcl_visualizer.h>        // 点云可视化头
 #include <pcl/features/range_image_border_extractor.h>// 深度图边缘提取头
 #include <pcl/keypoints/narf_keypoint.h> // NARF关键点计算头
 #include <pcl/features/narf_descriptor.h>// NARF描述子头
 #include <pcl/console/parse.h>           // 命令行解析头
 #include <pcl/common/file_io.h> // 用于获取没有拓展名的文件
 
 typedef pcl::PointXYZ PointType;
 
 float angular_resolution = 0.1875f; // 角度分辨率
 float support_size = 20.0f; // 关键点计算范围(计算范围球的半径)
 pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME; // 深度图坐标系
 bool setUnseenToMaxRange = false;  // 不设置深度范围
 bool rotation_invariant = true;	// 是否保持旋转不变性
 
 // --------------
 // -----输出帮助信息-----
// --------------
void printUsage (const char* progName)
 {
   std::cout << "\n\nUsage: "<<progName<<" [options] <scene.pcd>\n\n"
             << "Options:\n"
             << "-------------------------------------------\n"
             << "-r <float>   angular resolution in degrees (default "<<angular_resolution<<")\n"
             << "-c <int>     coordinate frame (default "<< (int)coordinate_frame<<")\n"
             << "-m           Treat all unseen points to max range\n"
             << "-s <float>   support size for the interest points (diameter of the used sphere - "
                                                                   "default "<<support_size<<")\n"
             << "-o <0/1>     switch rotational invariant version of the feature on/off"
             <<               " (default "<< (int)rotation_invariant<<")\n"
             << "-h           this help\n"
             << "\n\n";
 }
 
 void setViewerPose (pcl::visualization::PCLVisualizer& viewer, const Eigen::Affine3f& viewer_pose)
 {
   Eigen::Vector3f pos_vector = viewer_pose * Eigen::Vector3f (0, 0, 0);
   Eigen::Vector3f look_at_vector = viewer_pose.rotation () * Eigen::Vector3f (0, 0, 1) + pos_vector;
   Eigen::Vector3f up_vector = viewer_pose.rotation () * Eigen::Vector3f (0, -1, 0);
   viewer.setCameraPosition (pos_vector[0], pos_vector[1], pos_vector[2],
                             look_at_vector[0], look_at_vector[1], look_at_vector[2],
                             up_vector[0], up_vector[1], up_vector[2]);
 }
 

 int main (int argc, char** argv)
 {

   if (pcl::console::find_argument (argc, argv, "-h") >= 0)
   {
     printUsage (argv[0]);
     return 0;
   }
   if (pcl::console::find_argument (argc, argv, "-m") >= 0)
   {
     setUnseenToMaxRange = true;
     std::cout << "Setting unseen values in range image to maximum range readings.\n";
   }
   if (pcl::console::parse (argc, argv, "-o", rotation_invariant) >= 0)
     std::cout << "Switching rotation invariant feature version "<< (rotation_invariant ? "on" : "off")<<".\n";
   int tmp_coordinate_frame;
   if (pcl::console::parse (argc, argv, "-c", tmp_coordinate_frame) >= 0)
   {
     coordinate_frame = pcl::RangeImage::CoordinateFrame (tmp_coordinate_frame);
     std::cout << "Using coordinate frame "<< (int)coordinate_frame<<".\n";
   }
   if (pcl::console::parse (argc, argv, "-s", support_size) >= 0)
     std::cout << "Setting support size to "<<support_size<<".\n";
   if (pcl::console::parse (argc, argv, "-r", angular_resolution) >= 0)
     std::cout << "Setting angular resolution to "<<angular_resolution<<"deg.\n";
   angular_resolution = pcl::deg2rad (angular_resolution);
   
   // 读入PCD点云文件或创造出一些点云
   pcl::PointCloud<PointType>::Ptr point_cloud_ptr (new pcl::PointCloud<PointType>);
   pcl::PointCloud<PointType>& point_cloud = *point_cloud_ptr;
   pcl::PointCloud<pcl::PointWithViewpoint> far_ranges;
   Eigen::Affine3f scene_sensor_pose (Eigen::Affine3f::Identity ());
   std::vector<int> pcd_filename_indices = pcl::console::parse_file_extension_argument (argc, argv, "pcd");
   if (!pcd_filename_indices.empty ())
   {
    std::string filename = argv[pcd_filename_indices[0]];
    if (pcl::io::loadPCDFile (filename, point_cloud) == -1)
    {
      std::cerr << "Was not able to open file \""<<filename<<"\".\n";
      printUsage (argv[0]);
      return 0;
    }
    scene_sensor_pose = Eigen::Affine3f (Eigen::Translation3f (point_cloud.sensor_origin_[0],
                                                               point_cloud.sensor_origin_[1],
                                                               point_cloud.sensor_origin_[2])) *
                        Eigen::Affine3f (point_cloud.sensor_orientation_);
    std::string far_ranges_filename = pcl::getFilenameWithoutExtension (filename)+".pcd";
    if (pcl::io::loadPCDFile (far_ranges_filename.c_str (), far_ranges) == -1)
      std::cout << "Far ranges file \""<<far_ranges_filename<<"\" does not exists.\n";
  }
  else
  {
    setUnseenToMaxRange = true;
    std::cout << "\nNo *.pcd file given => Generating example point cloud.\n\n";
    for (float x=-0.5f; x<=0.5f; x+=0.01f)
    {
      for (float y=-0.5f; y<=0.5f; y+=0.01f) 
           {
        PointType point;  point.x = x;  point.y = y;  point.z = 2.0f - y;
        point_cloud.push_back (point);
      }
    }
    point_cloud.width = point_cloud.size ();  point_cloud.height = 1;
  }
  
  // 利用点云创造深度图
  float noise_level = 0.0;
  float min_range = 0.0f;
  int border_size = 1;
  pcl::RangeImage::Ptr range_image_ptr (new pcl::RangeImage);
  pcl::RangeImage& range_image = *range_image_ptr;   
  range_image.createFromPointCloud (point_cloud, angular_resolution, pcl::deg2rad (60.0f), pcl::deg2rad (45.0f),
                                   scene_sensor_pose, coordinate_frame, noise_level, min_range, border_size);
  range_image.integrateFarRanges (far_ranges);
  if (setUnseenToMaxRange)
    range_image.setUnseenToMaxRange ();
  
  // 显示点云
  pcl::visualization::PCLVisualizer viewer ("3D Viewer");
  viewer.setBackgroundColor (1, 1, 1);
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> range_image_color_handler (range_image_ptr, 0, 0, 0);
  viewer.addPointCloud (range_image_ptr, range_image_color_handler, "range image");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "range image");
  viewer.initCameraParameters ();
  setViewerPose (viewer, range_image.getTransformationToWorldSystem ());
  
  // 显示深度图
  pcl::visualization::RangeImageVisualizer range_image_widget ("Range image");
 range_image_widget.showRangeImage (range_image);
  
 // 提取NARF特征
  pcl::RangeImageBorderExtractor range_image_border_extractor;  
 pcl::NarfKeypoint narf_keypoint_detector; 
 narf_keypoint_detector.setRangeImageBorderExtractor (&range_image_border_extractor);//深度图像边缘点提取
  narf_keypoint_detector.setRangeImage (&range_image);
  narf_keypoint_detector.getParameters ().support_size = support_size;
  
  pcl::PointCloud<int> keypoint_indices;// 关键点序列
 narf_keypoint_detector.compute (keypoint_indices);// 计算narf关键点,并按照序列排序
  std::cout << "Found "<<keypoint_indices.size ()<<" key points.\n";


  pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints_ptr (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>& keypoints = *keypoints_ptr;
  keypoints.resize (keypoint_indices.size ());
  for (std::size_t i=0; i<keypoint_indices.size (); ++i)
    keypoints[i].getVector3fMap () = range_image[keypoint_indices[i]].getVector3fMap ();
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> keypoints_color_handler (keypoints_ptr, 0, 255, 0);
  viewer.addPointCloud<pcl::PointXYZ> (keypoints_ptr, keypoints_color_handler, "keypoints");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "keypoints");
  viewer.initCameraParameters();
  viewer.saveScreenshot("screenshot.png");
  // 为这些关键点计算NARF描述子
  std::vector<int> keypoint_indices2;
  keypoint_indices2.resize (keypoint_indices.size ());
  for (unsigned int i=0; i<keypoint_indices.size (); ++i) 
    keypoint_indices2[i]=keypoint_indices[i];
  pcl::NarfDescriptor narf_descriptor (&range_image, &keypoint_indices2);
  narf_descriptor.getParameters ().support_size = support_size;
  narf_descriptor.getParameters ().rotation_invariant = rotation_invariant;
 pcl::PointCloud<pcl::Narf36> narf_descriptors;
 narf_descriptor.compute (narf_descriptors);
  std::cout << "Extracted "<<narf_descriptors.size ()<<" descriptors for "
                      <<keypoint_indices.size ()<< " keypoints.\n";
  while (!viewer.wasStopped ())
  {
    viewer.spinOnce ();
  }
}

请添加图片描述

2.4 SIFT关键点

SIFT3D算法是一种基于高斯差分和尺度空间的点云关键点提取算法。它通过在多个尺度下对点云进行高斯滤波和差分操作,来提取稳定性和尺度不变性的关键点。

PCL

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/keypoints/sift_keypoint.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/time.h>
 
namespace pcl
{
	template<>
	struct SIFTKeypointFieldSelector<PointXYZ>
	{
		inline float
			operator () (const PointXYZ &p) const
		{
			return p.z;
		}
	};
}
 
int main()
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("second_radius_cloud.pcd", *cloud_xyz) == -1) // load the file
	{
		PCL_ERROR("Couldn't read file");
		return -1;
	}
	std::cout << "points: " << cloud_xyz->points.size() << std::endl;
 
	// Parameters for sift computation
	const float min_scale = 5.0f; //the standard deviation of the smallest scale in the scale space
	const int n_octaves = 6;//the number of octaves (i.e. doublings of scale) to compute
	const int n_scales_per_octave = 4;//the number of scales to compute within each octave
	const float min_contrast = 1.0f;//the minimum contrast required for detection
 
 
	pcl::console::TicToc time;
	time.tic();
	// Estimate the sift interest points using z values from xyz as the Intensity variants
	pcl::SIFTKeypoint<pcl::PointXYZ, pcl::PointWithScale> sift;
	pcl::PointCloud<pcl::PointWithScale> result;
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
	sift.setSearchMethod(tree);
	sift.setScales(min_scale, n_octaves, n_scales_per_octave);
	sift.setMinimumContrast(min_contrast);
	sift.setInputCloud(cloud_xyz);
	sift.compute(result);
	std::cout << "Computing the SIFT points takes " << time.toc() / 1000 << "seconds" << std::endl;
	std::cout << "No of SIFT points in the result are " << result.points.size() << std::endl;
 
	// Copying the pointwithscale to pointxyz so as visualize the cloud
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_temp(new pcl::PointCloud<pcl::PointXYZ>);
	copyPointCloud(result, *cloud_temp);
	std::cout << "SIFT points in the result are " << cloud_temp->points.size() << std::endl;
	// Visualization of keypoints along with the original cloud
	pcl::visualization::PCLVisualizer viewer("PCL Viewer");
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> keypoints_color_handler(cloud_temp, 0, 255, 0);
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud_xyz, 255, 0, 0);
	viewer.setBackgroundColor(0.0, 0.0, 0.0);
	viewer.addPointCloud(cloud_xyz, cloud_color_handler, "cloud");//add point cloud
	viewer.addPointCloud(cloud_temp, keypoints_color_handler, "keypoints");//add the keypoints
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "keypoints");
	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}
	return 0;
 
}

请添加图片描述

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

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

相关文章

C++模拟实现——list

一、成员变量及其基本结构 1.基本结构模型 本质是一个带头双向循环列表&#xff0c;将节点进行封装&#xff0c;并且为了方便使用&#xff0c;进行重定义 2.节点的封装定义 template<class T>//定义节点struct list_node{list_node<T>* _prev;list_node<T>…

linux性能分析(三)CPU篇(一)基础

一 CPU篇 遗留&#xff1a; 负载与cpu关系、负载与线程的关系? ① CPU 相关概念 1、physical 物理CPU个数 --> 一般一个实体 2、cpu 核数 3、逻辑CPU个数 逻辑核 4、超线程 super thread 技术 5、各种cpu的计算方式物理 physical CPU的个数&#xff1a; physical id逻…

易点易动固定资产管理系统引入RFID手持终端助力固定资产盘点

在现代商业环境中&#xff0c;固定资产盘点和管理对企业的运营至关重要。然而&#xff0c;传统的手工盘点方法已经无法满足企业对效率和准确性的要求。为了解决这一问题&#xff0c;易点易动固定资产管理系统引入RFID&#xff08;射频识别&#xff09;手持终端&#xff0c;为固…

北京卫视《为你喝彩》——星辰天合 CEO 胥昕,他专攻 SDS 让“数据常青”

10 月 18 日晚&#xff0c;北京卫视《为你喝彩》栏目播出&#xff0c;主题为《你有没有为梦想拼过命&#xff1f;听创业者说》&#xff0c;星辰天合 CEO 胥昕作为主人公之一&#xff0c;讲述了自己的创业故事。 如下内容摘自北京卫视&#xff1a; 青春总有着万般姿态&#xf…

图数据库实践 - 如何将图数据库应用于对公信贷

导读 日前&#xff0c;在经济形势和政策环境下&#xff0c;银行信贷结构进一步调整&#xff0c;民营企业、小微企业、绿色信贷投放力度持续加大。而坚持金融服务实体经济是政府的一贯主张&#xff0c;据相关工作报告指出&#xff0c;要求用好普惠小微贷款支持工具&#xff0c;…

为什么需要协调能力?如何提高协调能力?

协调能力指的是协作与调和&#xff0c;属于综合性能力的体现&#xff0c;涉及到表达&#xff0c;沟通&#xff0c;逻辑等方面&#xff0c;在日常生活中缺乏协调能力&#xff0c;也许影响并不太大&#xff0c;但是如果在职业发展中&#xff0c;协调能力就尤为重要&#xff0c;尤…

【公益案例展】广碳所——恒生电子基于区块链技术打造区域性碳中和登记系统...

‍ 恒生电子公益案例 本项目案例由恒生电子投递并参与数据猿与上海大数据联盟联合推出的 #榜样的力量# 《2023中国数据智能产业最具社会责任感企业》榜单/奖项”评选。 ‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 全球气候变暖、温室效应明显、二氧化碳排放增多&#…

virtualBox虚拟机安装多个+主机访问虚拟机+虚拟机访问外网配置

目的&#xff1a;本机安装3个虚拟机 一、虚拟机安装&#xff1a;Oracle VM VirtualBox (https://www.virtualbox.org/)源代码可下载&#xff0c;且免费使用 1、https://www.virtualbox.org/ 进入网站中Download 模块选择与自己电脑系统相应的下载包下载即可 如果安装过程报错如…

京东数据分析:2023厨房小电市场遇冷,空气炸锅等明星产品被抛弃

过去几年间&#xff0c;宅经济的爆发带火了酸奶机、煮蛋器、豆浆机、空气炸锅、养生壶等&#xff0c;一众外观小巧、功能丰富、价格相对便宜的厨房小家电。但随着年轻人走出家门回归工作岗位&#xff0c;厨房小家电们却步入了艰难时刻。 如今&#xff0c;厨房小家电们似乎正在经…

论坛介绍 | COSCon'23 人工智能(A)

众多开源爱好者翘首期盼的开源盛会&#xff1a;第八届中国开源年会&#xff08;COSCon23&#xff09;将于 10月28-29日在四川成都市高新区菁蓉汇举办。本次大会的主题是&#xff1a;“开源&#xff1a;川流不息、山海相映”&#xff01;各位新老朋友们&#xff0c;欢迎到成都&a…

NET7下用WebSocket做简易聊天室

NET7下用WebSocket做简易聊天室 步骤&#xff1a; 建立NET7的MVC视图模型控制器项目创建websocket之间通信的JSON字符串对应的实体类一个房间用同一个Websocketwebsocket集合类&#xff0c;N个房间创建websocket中间件代码Program.cs中的核心代码&#xff0c;使用Websocket聊…

C语言利用已知公式估算e的近似值

编写一个函数&#xff0c;由公式e11/1&#xff01;1/2! 1/3!…&#xff0c;计算不同精确度下e的近似值。要求能够用键盘揄入指定的精确度&#xff0c;并输出该精确度下的e的近似值 例如&#xff1a;输入精确度为10e-6&#xff0c;则输出结果&#xff1a;2.718279。 #include &…

原来你根本不会找资源~

作为一名合格的传媒工作者&#xff0c;我不允许还有人不会找资源&#xff0c;下面这个四个网站必须码住&#xff0c;百分之八十的素材都来源于这些&#xff01;一、XDown【xdown.chuangzuoniu.com】 在线视频下载器&#xff0c;支持1000主流在线视频网站&#xff0c;一键下载多…

iOS原生、Android 原生, flutter 三种方式给照片流添加文字(水印)

效果图:三中代码实现的效果差不多 Swift:代码 import UIKitclass ImageWatermarking: NSObject {static func textToImage(drawText text: String, inImage initImage: UIImage, atPoint point: CGPoint) -> UIImage {let textColor = UIColor.whitelet textFont = UIFon…

如何选择一款好的护眼台灯?双十一必入护眼台灯推荐

随着科技的不断发展&#xff0c;工作时使用电子设备越来越普遍,如何保护我们的眼睛不受蓝光、频闪等危害就变得极其重要了。护眼台灯&#xff0c;顾名思义就是保护眼睛的台灯&#xff0c;其工作原理是在光源处使用特殊的防蓝光灯珠&#xff0c;并通过控制电流的稳定性来达到防频…

easyrecovery2024数据恢复软件最新版本下载

easyrecovery是PC上数据恢复领域相当给力的应用软件之一&#xff0c;它具有操作安全&#xff0c;价格便宜&#xff0c;支持用户自主操作等特点&#xff0c;能支持从各种存储介质恢复删除、格式化或者丢失的文件&#xff0c;从任何存储介质设备上的损坏&#xff0c;删除&#xf…

最简网卡驱动

在内核注册自定义的网卡驱动&#xff0c;并通过打印用户空间和内核的交互数据&#xff0c;可以更深层次的理解网络协议。 驱动代码&#xff1a; #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/netdevi…

每日一题 2525. 根据规则将箱子分类 (简单)

简单题&#xff0c;直接分类就好 class Solution:def categorizeBox(self, length: int, width: int, height: int, mass: int) -> str:if length > 10**4 or width > 10**4 or height > 10**4 or length*width*height > 10**9:return "Both" if mas…

短链服务如何定制域名

短链接不仅方便推广&#xff0c;而且还能能够保护原来的落地域名&#xff0c;为落地域名提供一个屏障&#xff0c;那么短链接的自定义域名怎么绑定呢&#xff1f;接下来就为大家带来详细的绑定步骤&#xff0c;需要的伙伴可以来看看。 域名绑定步骤 首先您或您的公司团队需要拥…