CUDA小白 - NPP(2) - Arithmetic and Logical Operations(1)

news2024/11/14 20:59:07

cuda小白
原文链接 NPP

GPU架构近些年也有不少的变化,具体的可以参考别的博主的介绍,都比较详细。还有一些cuda中的专有名词的含义,可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》

常见的NppStatus,可以看这里。

如有问题,请指出,谢谢

Arithmetic Operations

当前模块主要是加减乘除,abs,平方,矩阵相乘,开根,ln,exp等。不同相同功能,以其中一个为例进行介绍。

AddC

针对图像中每一个像素添加一个常量值。与之类似的还有MulC,SubC,DivC,AbsDiffC,MulScale
大概接口样式:

// 两个结果的区别在于,有I的结果可以就原始的图像地址进行操作,无需进行拷贝
// Sfs的含义 表示可以对图像的数值范围进行约束操作。
NppStatus nppiAddC_[数据类型]_C[通道数]RSfs_[是否使用流]
NppStatus nppiAddC_[数据类型]_C[通道数]IRSfs_[是否使用流]

以为三通道的uint8_t的图像数据为例子:

NppStatus nppiAddC_8u_C3RSfs(const Npp8u * pSrc1,
							 int nSrc1Step,
							 const Npp8u aConstants[3],
							 Npp8u *pDst,
							 int nDstStep,
							 NppiSize oSizeROI,
							 int nScaleFactor);
NppStatus nppiAddC_8u_C3RSfs(const Npp8u aConstants[3],
							 Npp8u *pDst,
							 int nDstStep,
							 NppiSize oSizeROI,
							 int nScaleFactor);	
code
#include <iostream>
#include <cuda_runtime.h>
#include <npp.h>
#include <opencv2/opencv.hpp>

#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }

int main() {
  std::string directory = "../";
  // =============== load image ===============
  cv::Mat image = cv::imread(directory + "dog.png");
  if (image.empty()) {
    std::cout << "Load image error!" << std::endl;
    return -1;
  }

  int image_width = image.cols;
  int image_height = image.rows;
  int image_size = image_width * image_height * 3 * sizeof(uint8_t);
  std::cout << "Image info : image_width = " << image_width
            << ", image_height = " << image_height << std::endl;

  // =============== malloc && cpy ===============
  uint8_t *in_ptr, *in_ptr2, *out_ptr, *roi_out_ptr;
  cudaMalloc((void**)&in_ptr, image_size);
  cudaMalloc((void**)&in_ptr2, image_size);
  cudaMalloc((void**)&out_ptr, image_size);
  cudaMalloc((void**)&roi_out_ptr, image_size);
  cudaMemcpy(in_ptr, image.data, image_size, cudaMemcpyHostToDevice);
  cudaMemcpy(in_ptr2, image.data, image_size, cudaMemcpyHostToDevice);

  uint8_t host_constant[3] = { (uint8_t)0, (uint8_t)20, (uint8_t)0 };

  NppiSize roi1, roi2;
  roi1.width = image_width;
  roi1.height = image_height;
  roi2.width = image_width / 2;
  roi2.height = image_height / 2;
  
  // nppiAddC_8u_C3RSfs
  cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);
  NppStatus status;
  status = nppiAddC_8u_C3RSfs(in_ptr, image_width * 3, host_constant, out_ptr, 
                              image_width * 3, roi1, 0);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiAddC_8u_C3RSfs failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr, image_size, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "add_constant.jpg", out_image);

  status = nppiAddC_8u_C3RSfs(in_ptr, image_width * 3, host_constant, out_ptr, image_width * 3, 
                              roi1, 1);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiAddC_8u_C3RSfs failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr, image_size, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "add_constant_scale.jpg", out_image);

  status = nppiAddC_8u_C3RSfs(in_ptr, image_width * 3, host_constant, out_ptr, image_width * 3, 
                              roi2, 0);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiAddC_8u_C3RSfs failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr, image_size, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "add_constant_roi.jpg", out_image);

  // free
  CUDA_FREE(in_ptr)
  CUDA_FREE(in_ptr2)
  CUDA_FREE(out_ptr)
  CUDA_FREE(roi_out_ptr)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")

add_executable(test test.cpp)
target_link_libraries(test
                      ${OpenCV_LIBS}
                      ${CUDA_LIBS}
)
result

请添加图片描述
注意点:

  1. 对图像的进行值的范围进行一定的约束,最初的图像RGB的值都是[0, 255],如果对应的scale设置为1的时候,相当于将数值的范围变为2的-nScaleFactor倍数,即[0, 128],超过128的会变成128,因此整体的图像色调会变暗;同样的,如果设置为-1,则整体的会变为2倍,因为存图的限制只能是[0, 255],所以整体看起来会变亮。
  2. 如果指定的roi不是整张图的时候,由于roi的类型是NppiSize(width, height),因此输入的指针不是指向图像的起始位置,而是roi的起始位置。
  3. MulScale相较于MulC来说,默认nScaleFactor为0;
  4. AbsDiffC中主要功能就是得到整张图像与host_constant的绝对差值。
  5. 每个结果都有一个对应的包含cudastream的版本,按需使用。

Add

与AddC不同的是,Add输入的是两张图像。同样的还有Mul,MulScale,Sub,Div,Div_round,Abs,AbsDiff,Sqr,Sqrt,Ln,Exp。(由于Abs,AbsDiff,Sqr,Sqrt,Ln,Exp在图像出列方面使用的不是很多,就不细述)。
以uint8_t的三通道图像为例:

// 命名规则与nppiAddC*类似
NppStatus nppiAdd_8u_C3RSfs(const Npp8u * pSrc1,
							int nSrc1Step,
						    const Npp8u *pSrc2,
							int nSrc2Step,
							Npp8u * pDst,
							int nDstStep,
							NppiSize oSizeROI,
							int nScaleFactor);
NppStatus nppiAdd_8u_C3IRSfs(const Npp8u *pSrc,
							 int nSrcStep,
							 Npp8u *pSrcDst,
							 int nSrcDstStep,
							 NppiSize oSizeROI,
							 int nScaleFactor);
code
#include <iostream>
#include <cuda_runtime.h>
#include <npp.h>
#include <opencv2/opencv.hpp>

#define PRINT_VALUE(value) {  \
  std::cout << "[GPU] " << #value << " = " << value << std::endl; }

#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }

int main() {
  std::string directory = "../";
  // =============== load image ===============
  cv::Mat image = cv::imread(directory + "dog.png");
  if (image.empty()) {
    std::cout << "Load image error!" << std::endl;
    return -1;
  }

  int image_width = image.cols;
  int image_height = image.rows;
  int image_size = image_width * image_height * 3 * sizeof(uint8_t);
  std::cout << "Image info : image_width = " << image_width
            << ", image_height = " << image_height << std::endl;

  // =============== malloc && cpy ===============
  uint8_t *in_ptr, *in_ptr2, *out_ptr, *roi_out_ptr;
  cudaMalloc((void**)&in_ptr, image_size);
  cudaMalloc((void**)&in_ptr2, image_size);
  cudaMalloc((void**)&out_ptr, image_size);
  cudaMalloc((void**)&roi_out_ptr, image_size);
  cudaMemcpy(in_ptr, image.data, image_size, cudaMemcpyHostToDevice);
  cudaMemcpy(in_ptr2, image.data, image_size, cudaMemcpyHostToDevice);

  NppiSize roi1, roi2;
  roi1.width = image_width;
  roi1.height = image_height;
  roi2.width = image_width / 2;
  roi2.height = image_height / 2;
  
  // nppiAdd_8u_C3RSfs
  cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);
  NppStatus status;
  status = nppiAdd_8u_C3RSfs(in_ptr, image_width * 3, in_ptr2, image_width * 3, out_ptr, 
                             image_width * 3, roi1, 0);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiAdd_8u_C3RSfs failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr, image_size, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "add.jpg", out_image);

  status = nppiAdd_8u_C3RSfs(in_ptr, image_width * 3, in_ptr2, image_width * 3, out_ptr, 
                             image_width * 3, roi1, 1);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiAdd_8u_C3RSfs failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr, image_size, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "add_scale.jpg", out_image);

  status = nppiAdd_8u_C3RSfs(in_ptr, image_width * 3, in_ptr2, image_width * 3, out_ptr, 
                             image_width * 3, roi2, 0);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiAdd_8u_C3RSfs failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr, image_size, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "add_roi.jpg", out_image);

  // free
  CUDA_FREE(in_ptr)
  CUDA_FREE(in_ptr2)
  CUDA_FREE(out_ptr)
  CUDA_FREE(roi_out_ptr)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")

add_executable(test test.cpp)
target_link_libraries(test
                      ${OpenCV_LIBS}
                      ${CUDA_LIBS}
)
result

请添加图片描述
注意点:

  1. nScaleFactor与AddC中的功能一致。roi的操作也与AddC中的一致。
  2. 由于使用的是两个相同的图片进行相加,因此在nScaleFactor为1的时候,所有的数值都变成原来的值,因此保存的图像与原图一致。
  3. 同样有cudastream版本,按需使用。

AddWeighted

将特定区域的图像进行填充weight

NppStatus nppiAddWeighted_8u32f_C1IR(const Npp8u *pSrc,
									 int nSrcStep,
									 Npp32f * pSrcDst,
									 int nSrcDstStep,
									 NppiSize oSizeROI,
								     Npp32f nAlpha);
NppStatus nppiAddWeighted_8u32f_C1IMR(const Npp8u *pSrc,
									  int nSrcStep,
									  const Npp8u *pMask,
									  int nMaskStep,
									  Npp32f * pSrcDst,
									  int nSrcDstStep,
									  NppiSize oSizeROI,
									  Npp32f nAlpha);	
code
#include <iostream>
#include <cuda_runtime.h>
#include <npp.h>
#include <opencv2/opencv.hpp>

#define PRINT_VALUE(value) {  \
  std::cout << "[GPU] " << #value << " = " << value << std::endl; }

#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }

int main() {
  std::string directory = "../";
  // =============== load image ===============
  cv::Mat image = cv::imread(directory + "dog.png");
  if (image.empty()) {
    std::cout << "Load image error!" << std::endl;
    return -1;
  }

  cv::Mat gray;
  cv::cvtColor(image, gray, CV_BGR2GRAY);
  cv::imwrite(directory + "gray.jpg", gray);

  int image_width = gray.cols;
  int image_height = gray.rows;
  int image_size = image_width * image_height;
  std::cout << "Image info : image_width = " << image_width
            << ", image_height = " << image_height << std::endl;

  cv::Mat mat_mask = cv::Mat::ones(image_height, image_width, CV_8UC1);

  cv::Rect rc_center = cv::Rect(image_width / 4, image_height / 4, 
                                image_width / 2, image_height / 2);
  mat_mask(rc_center) = cv::Mat::ones(image_height / 2, image_width / 2, CV_8UC1) * 255;
  cv::imwrite(directory + "mask.jpg", mat_mask);

  // =============== malloc && cpy ===============
  uint8_t *in_ptr, *mask;
  cudaMalloc((void**)&in_ptr, image_size * sizeof(uint8_t));
  cudaMalloc((void**)&mask, image_size * sizeof(uint8_t));
  cudaMemcpy(in_ptr, gray.data, image_size, cudaMemcpyHostToDevice);
  cudaMemcpy(mask, mat_mask.data, image_size, cudaMemcpyHostToDevice);

  float *out_ptr, *out_ptr1, *out_ptr2;
  cudaMalloc((void**)&out_ptr, image_size * sizeof(float));
  cudaMalloc((void**)&out_ptr1, image_size * sizeof(float));
  cudaMalloc((void**)&out_ptr2, image_size * sizeof(float));
  
  NppiSize roi1, roi2;
  roi1.width = image_width;
  roi1.height = image_height;
  roi2.width = image_width / 2;
  roi2.height = image_height / 2;
  
  // nppiAdd_8u_C3RSfs
  cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_32FC1);
  NppStatus status;
  status = nppiAddWeighted_8u32f_C1IMR(in_ptr, image_width * sizeof(uint8_t), 
                                       mask, image_width * sizeof(uint8_t), 
                                       out_ptr, image_width * sizeof(float), 
                                       roi1, 1.0);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiAddWeighted_8u32f_C1IMR failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr, image_size * sizeof(float), cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "addweight.jpg", out_image);

  status = nppiAddWeighted_8u32f_C1IMR(in_ptr, image_width * sizeof(uint8_t), 
                                       mask, image_width * sizeof(uint8_t), 
                                       out_ptr1, image_width * sizeof(float), 
                                       roi1, 0.5);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiAddWeighted_8u32f_C1IMR failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, image_size * sizeof(float), cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "addweight_scale.jpg", out_image);

  status = nppiAddWeighted_8u32f_C1IMR(in_ptr, image_width * sizeof(uint8_t), 
                                       mask, image_width * sizeof(uint8_t), 
                                       out_ptr2, image_width * sizeof(float), 
                                       roi2, 0.5);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiAddWeighted_8u32f_C1IMR failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr2, image_size * sizeof(float), cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "addweight_roi_scale.jpg", out_image);

  // free
  CUDA_FREE(in_ptr)
  CUDA_FREE(mask)
  CUDA_FREE(out_ptr)
  CUDA_FREE(out_ptr1)
  CUDA_FREE(out_ptr2)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")

add_executable(test test.cpp)
target_link_libraries(test
                      ${OpenCV_LIBS}
                      ${CUDA_LIBS}
)
result

请添加图片描述
注意点:
1.nAlpha是针对原图中的每一个像素的值需要添加的权重,mask仅影响目标位置中那些部分需要输出。
2. roi表示输入的区域约束。

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

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

相关文章

Sentinel配置的blockHandler方法不生效

①首先配置流控的资源名跟SentinelResource中的Value配置的一定要一直且唯一 ②其次blockhandler后面的方法一定要跟下面指定的方法名称是一样的 ③也就是我犯下的错误&#xff0c;一定要注意是上面那个才是Sentinel的&#xff0c;下面的是sun公司的…我说呢&#xff0c;一直…

Java“牵手”京东商品列表数据,关键词搜索京东商品数据接口,京东API申请指南

京东商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取京东商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问京东商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…

Nacos 配置管理及相关使用

文章目录 Nacos 配置管理一、统一配置管理1、在Nacos 中添加配置文件2、从微服务拉取配置3、配置实现步骤&#xff08;1&#xff09;引入 nacos-config 依赖&#xff08;2&#xff09;添加 bootstrap.yml&#xff08;4&#xff09;在 nacos 中添加配置 二、配置热更新1、配置热…

Sentry 是一个开源的错误监控和日志聚合平台-- 通过docker-compose 安装Sentry

概述 Sentry 是一个开源的错误监控和日志聚合平台&#xff0c;用于帮助开发团队实时监控和调试应用程序中的错误和异常。它可以捕获应用程序中的错误和异常&#xff0c;并提供详细的错误报告&#xff0c;包括错误堆栈跟踪、环境信息、用户信息等。这些报告可以帮助开发团队快速…

关于C语言参数传递的

一、C语言参数传递是整体带入 #include <stdio.h> #define DF(a,b) (a2*b) int main() { int s5; int k DF((s1),(s-3)); printf("%d",k); }输出结果 原因&#xff1a; #define DF(a,b) (a2*b) int k DF((s1),(s-3)); //等效 int k DF((s1)2 * (s-3)); …

CRM软件排行榜靠前的都有哪些特点?

CRM软件是企业管理客户关系的重要工具&#xff0c;它可以帮助企业提高销售效率、增强客户满意度、提升市场竞争力。在众多的CRM软件中&#xff0c;排名靠前的CRM软件有哪些&#xff1f; 1、功能全面 Zoho CRM提供了从销售、营销、客服到AI人工智能、BI数据分析再到定制开发等…

Dockerfile 使用教程

1.Dockerfile 1.1 什么是Dockerfile Dockerfile可以认为是 Docker镜像的描述文件&#xff0c;是由一系列命令和参数构成的脚本 。主要作用是 用来构建docker镜像的构建文件 。 通过架构图可以看出通过DockerFile可以直接构建镜像 1.2 Dockerfile解析过程 构建镜像步骤&#xf…

Java中的Reference

1. 常用四种引用 快速记忆法&#xff1a;“硬(俗称的强引用) --> 软(SoftReference) --> 弱(WeakReference) --> 虚(PhantomReference)” 此处将常说的“强引用”记忆成“硬引用”可以对应到次席的“软引用”&#xff08;反义词&#xff1a;硬-软&#xff09;这样更容…

ExpressLRS开源代码之框架结构

ExpressLRS开源代码之框架结构 1. 源由2. Arduino应用框架3. ExpressLRS应用框架4. 硬件设计框架4.1 单天线4.2 双天线单PA4.3 双天线双PA 5. 应用软件设计6. 参考资料 1. 源由 最近为了理解《ExpressLRS开源之基本调试数据含义》&#xff0c;做了一些源代码的研读。 概念、文…

Nginx基础+高级(2022版):待更新

1. 文章说明 说明&#xff1a;目前讲的是第一部分nginx核心技术篇&#xff0c;后需篇章会以第一部分为核心技术篇为基础来展开深度讲解&#xff0c;详情关注后续课程的发布。 2. 介绍和准备环境 2.1 介绍 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器&#xf…

WebDAV之π-Disk派盘 + 人升

人升是一款融入了游戏化元素的待办事项应用,旨在为用户提供一种记录待办事项的过程像玩游戏打怪升级的体验。该应用致力于在保持实用性的基础上,扩展应用的乐趣。 在实用性方面,人升提供了以下功能: – 简洁界面:符合Material Design的简约界面,使新建待办事项变得更加轻…

嘉泰实业和您共创未来财富生活

每一次暖心的沟通都是一次公益,真诚不会因为它的渺小而被忽略;每一声问候都是一次公益,善意不会因为它的普通而被埋没。熟悉嘉泰实业的人都知道,这家企业不但擅长在金融理财领域里面呼风唤雨,同时也非常擅长在公益事业当中践行,属于企业的责任心,为更多有困难的群体带来大爱的传…

【机器视觉】HALCON目标图像检测实践(零基础版非常有用!)

开发环境&#xff1a; 基本思路&#xff1a; 灰度阈值处理特征提取 ps:思考&#xff1a;如何通过阈值处理后&#xff0c;后续缩小检测目标范围&#xff1f; 二值化、梯度阈值、自适应阈值等方法来增强图像的对比度&#xff0c;从而突出目标特征&#xff0c;进一步缩小检测目标…

对话永洪科技CEO何春涛:专注BI,决胜AI时代丨数据猿专访

大数据产业创新服务媒体 ——聚焦数据 改变商业 大数据、云计算、人工智能为代表的新一代信息技术走向普及&#xff0c;数据驱动业务&#xff0c;逐渐成为现代化企业管理、运作的日常。对于年均复合增长率超过20%的国内商业智能&#xff08;BI&#xff09;市场而言&#xff0c…

OpenHarmony 应用 ArkUI 状态管理开发范例

本文转载自《#2023 盲盒码 # OpenHarmony 应用 ArkUI 状态管理开发范例》&#xff0c;作者&#xff1a;zhushangyuan_ 本文根据橘子购物应用&#xff0c;实现 ArkUI 中的状态管理。 在声明式 UI 编程框架中&#xff0c;UI 是程序状态的运行结果&#xff0c;用户构建了一个 UI …

技术奇瑞高能出击,四大品牌联袂燃擎成都车展

8月25日&#xff0c;成都国际汽车展览会于中国西部国际博览城正式拉开帷幕。成都车展作为西南地区首屈一指的国内四大A级车展之一&#xff0c;不仅是下半年国内车市的风向标&#xff0c;也因天府之国弥漫着火锅味与茶香的烟火气而独具一番风味。成都车展上&#xff0c;奇瑞集团…

【校招VIP】前端算法考点之大数据相关

考点介绍&#xff1a; 大数据的关键技术分为分析技术和处理技术&#xff0c;可用于大数据分析的关键技术主要包括A/B测试&#xff0c;关联规则挖掘&#xff0c;数据挖掘&#xff0c;集成学习&#xff0c;遗传算法&#xff0c;机器学习&#xff0c;自然语言处理&#xff0c;模式…

17.看楼房

Description 小张在暑假时间进行了暑期社会调查。调查的内容是楼房的颜色如何影响人们的心情。于是他找到了一个楼房从左到右排成一排的小区&#xff0c;这个小区一共有 栋楼房&#xff0c;每个楼房有一个颜色 和一个高度 。小张调查的内容为每次他站在第 栋楼和第 栋楼之间向…

2240. 买钢笔和铅笔的方案数

文章目录 Tag题目来源题目解读解题思路复杂度分析写在最后 Tag 【枚举】【数学】 题目来源 2240. 买钢笔和铅笔的方案数 题目解读 现在你有一笔钱 total&#xff0c;用来购买钢笔和铅笔&#xff0c;它们的价格分别为 cost1 和 cost2&#xff0c;试问你可以有多少种不同的购…

CASAIM与北京协和医院达成合作,通过CT重建和3D打印技术为医学实验提供技术辅助和研究样本

近期&#xff0c;CASAIM与北京协和医院达成合作&#xff0c;通过CT重建和3D打印技术为医学实验提供技术辅助和研究样本&#xff0c;在实验样本的一致性和实验研究的严谨性原则下设计方案&#xff0c;推动产学研一体化发展。 北京协和医院是集医疗、教学、科研于一体的现代化综合…