OpenCV CUDA模塊設備層-----用于CUDA 紋理內存(Texture Memory)的封裝類cv::cudev::Texture

  • 操作系統:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 編程語言:C++11

算法描述

cv::cudev::Texture 是 OpenCV CUDA 模塊(opencv_cudaimgproc)中用于 CUDA 紋理內存(Texture Memory) 的封裝類。它主要用于在 CUDA 核函數中訪問圖像數據時,利用紋理內存的緩存機制來提升性能,特別是在圖像采樣、縮放、仿射變換等操作中。

  • 紋理內存是一種 只讀緩存內存,適合隨機訪問模式。
  • 它有緩存機制,對圖像空間局部性訪問非常友好。
  • 常用于圖像處理中的插值、旋轉、透視變換、濾波等任務。

cv::cudev::Texture 的作用

OpenCV 提供了 cv::cudev::Texture 類模板來綁定圖像數據到紋理內存中:

template <typename T>
class Texture : public PtrStepSzb
{
public:Texture();explicit Texture(const GpuMat& d_src);void bind(const GpuMat& d_src);void unbind();
};

你可以把它理解為一個“GPU 圖像紋理對象”,綁定后可以在核函數中使用類似 CPU 中 cv::getRectSubPix 或 cv::remap 的方式訪問像素。

使用步驟示例

步驟 1:包含頭文件

#include <opencv2/cudaimgproc.hpp>
#include <opencv2/cudev/ptr2d/texture.hpp>

步驟 2:綁定圖像到紋理內存

cv::cuda::GpuMat d_src = ...; // 輸入圖像
cv::cudev::Texture<uchar> tex;
tex.bind(d_src); // 綁定 uchar 類型的圖像到紋理內存

你也可以使用其他類型如 uchar3, float 等。
步驟 3:在 CUDA 核函數中訪問紋理內存

__global__ void sampleKernel(float* output, int width, int height) {int x = blockIdx.x * blockDim.x + threadIdx.x;int y = blockIdx.y * blockDim.y + threadIdx.y;if (x < width && y < height) {float u = static_cast<float>(x) / width;float v = static_cast<float>(y) / height;// 使用紋理采樣器讀取像素output[y * width + x] = tex2D(tex, u * width, v * height);}
}

注意:這里使用了 tex2D() 函數,這是 CUDA 運行時 API 中的標準紋理采樣函數。

步驟 4:調用核函數并釋放資源

dim3 block(16, 16);
dim3 grid((width + 15) / 16, (height + 15) / 16);sampleKernel<<<grid, block>>>();
cudaDeviceSynchronize();tex.unbind(); // 使用完記得解綁

注意事項

內容說明
只讀訪問Texture memory 是只讀的,不能寫入
數據類型支持支持 uchar, uchar4, float, float4 等常見格式
性能優化對圖像縮放、旋轉、仿射變換等操作特別有用
自動邊界處理支持 cudaAddressModeClamp, cudaAddressModeWrap 等尋址模式
需要綁定和解綁使用完畢要調用 unbind() 避免資源泄漏

代碼示例

頭文件:

#ifndef CUDA_UTILS_H
#define CUDA_UTILS_H#include <opencv2/opencv.hpp>
#include <opencv2/cudaimgproc.hpp>// 聲明在 .cu 文件中實現的函數
void resizeWithTexture(cv::cuda::GpuMat& d_src, cv::cuda::GpuMat& d_dst, float scale);#endif // CUDA_UTILS_H‘

cu文件:

#include "cuda_utils.h"
#include <opencv2/cudev/ptr2d/texture.hpp>using namespace cv;
using namespace cudev;#include <cuda_runtime.h>
#include <vector_types.h>
#include <iostream>// 定義 CUDA 檢查宏
#define CUDA_CHECK(call) \do { \cudaError_t err = call; \if (err != cudaSuccess) { \std::cerr << "CUDA error at " << __FILE__ << ":" << __LINE__ << ": " \<< cudaGetErrorString(err) << std::endl; \exit(EXIT_FAILURE); \} \} while (0)__global__ void resizeKernel(uchar* dst, int dst_cols, int dst_rows, size_t dst_step,float scale, int src_cols, int src_rows, cudaTextureObject_t texObj) {int x = blockIdx.x * blockDim.x + threadIdx.x;int y = blockIdx.y * blockDim.y + threadIdx.y;if (x < dst_cols && y < dst_rows) {float src_x = x / scale;float src_y = y / scale;// 使用紋理采樣器讀取像素值float val = tex2D<uchar>(texObj, src_x + 0.5f, src_y + 0.5f);dst[y * dst_step + x] = static_cast<uchar>(val);}
}void resizeWithTexture(cuda::GpuMat& d_src, cuda::GpuMat& d_dst, float scale) {cudaTextureObject_t texObj = 0;// 1. 創建 CUDA ArraycudaArray* cu_array = nullptr;// 獲取源圖像的通道數并創建對應格式的通道描述符int num_channels = d_src.channels();cudaChannelFormatDesc channel_desc;switch (num_channels) {case 1: channel_desc = cudaCreateChannelDesc<uchar>(); break;case 3: channel_desc = cudaCreateChannelDesc<uchar3>(); break;case 4: channel_desc = cudaCreateChannelDesc<uchar4>(); break;default:std::cerr << "Unsupported number of channels: " << num_channels << std::endl;exit(EXIT_FAILURE);
}CUDA_CHECK(cudaMallocArray(&cu_array, &channel_desc, d_src.cols, d_src.rows, cudaArrayDefault));// 2. 將圖像數據拷貝到 CUDA ArrayCUDA_CHECK(cudaMemcpy2DToArray(cu_array, 0, 0,d_src.data, d_src.step,d_src.cols, d_src.rows,cudaMemcpyDeviceToDevice));// 3. 配置紋理資源描述符cudaResourceDesc res_desc = {};memset(&res_desc, 0, sizeof(res_desc));res_desc.resType = cudaResourceTypeArray;res_desc.res.array.array = cu_array;// 4. 配置紋理描述符cudaTextureDesc tex_desc = {};memset(&tex_desc, 0, sizeof(tex_desc));tex_desc.addressMode[0] = cudaAddressModeClamp; // 邊界模式tex_desc.addressMode[1] = cudaAddressModeClamp;tex_desc.filterMode = cudaFilterModePoint;      // 最鄰近插值tex_desc.readMode = cudaReadModeElementType;tex_desc.normalizedCoords = 0;                  // 坐標單位為像素而非 [0,1]// 5. 創建紋理對象CUDA_CHECK(cudaCreateTextureObject(&texObj, &res_desc, &tex_desc, NULL));// 6. 啟動核函數dim3 block(16, 16);dim3 grid((d_dst.cols + block.x - 1) / block.x,(d_dst.rows + block.y - 1) / block.y);resizeKernel<<<grid, block>>>(d_dst.data, d_dst.cols, d_dst.rows, d_dst.step,scale, d_src.cols, d_src.rows, texObj);CUDA_CHECK(cudaDeviceSynchronize());// 7. 清理資源CUDA_CHECK(cudaDestroyTextureObject(texObj));CUDA_CHECK(cudaFreeArray(cu_array));
}

main.cpp:

#include "cuda_utils.h"  // 調用 CUDA 接口
#include <iostream>
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/opencv.hpp>int main()
{// 讀取圖像(灰度圖)cv::Mat h_src = cv::imread( "/media/dingxin/data/study/OpenCV/sources/images/Lenna.png", cv::IMREAD_GRAYSCALE );if ( h_src.empty() ){std::cerr << "Failed to load image!" << std::endl;return -1;}// 創建 GPU 圖像cv::cuda::GpuMat d_src, d_dst;d_src.upload( h_src );// 設置目標尺寸(放大兩倍)float scale = 2.0f;d_dst.create( cvRound( h_src.rows * scale ), cvRound( h_src.cols * scale ), h_src.type() );// 調用 CUDA 實現的縮放函數resizeWithTexture( d_src, d_dst, scale );// 下載結果cv::Mat h_dst;d_dst.download( h_dst );// 顯示結果cv::imshow( "Original", h_src );cv::imshow( "Resized (CUDA Texture)", h_dst );cv::waitKey( 0 );return 0;
}

運行結果

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/909685.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/909685.shtml
英文地址,請注明出處:http://en.pswp.cn/news/909685.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

自主學習-《Self-Adapting Language Models》

代碼&#xff1a; https://jyopari.github.io/posts/seal 擬人比喻&#xff1a; 學生把備考的東西&#xff0c;以自己的方式記成筆記精華&#xff0c;更有利于他的理解和記憶。 背景&#xff1a; Self-improving: 本文&#xff1a; 輸入外界知識&#xff0c;LLM將其整理為筆記(…

馬上行計劃管理后端架構

小程序日活未破萬低成本高可用及滾動發版實戰。 小程序已經積累很多用戶了&#xff0c;高可用及滾動發布已經提上日程。 日活未破萬&#xff0c;選購多臺多家云服務器或者自建機房搭建k8s(Kubernetes)&#xff0c;成本顯然有點太高了。因此取了折中的辦法本地和云端服務同時啟…

C++---類和對象(上)

1.類的定義 1.1類定義格式 首先我們引入一個新的關鍵字-----class&#xff0c;class定義一個類。 定義方法 跟我們之前定義結構體非常的像 那我們來簡單的看一個類的定義 我們C語言實現的時候&#xff0c;結構體和函數是分離的。但是現在不需要&#xff0c;我可以直接寫 …

UE5.5構建iOS失敗但沒有顯式錯誤信息的問題

報錯信息如下 UnrealBuildTool failed. See log for more details. (/Users/somebody/Library/Logs/Unreal Engine/LocalBuildLogs/UBA-UnrealDemo-IOS-Shipping_2.txt) AutomationException: UnrealBuildTool failed. See log for more details. (/Users/somebody/Library/Lo…

淺談 Unity XR:從混戰到統一,OpenXR 的演進與現實困境

一.引言 在 XR&#xff08;擴展現實&#xff09;技術日漸普及的今天&#xff0c;Unity 已成為開發 VR、AR 和 MR 應用的主流平臺。然而在這個生態蓬勃發展的背后&#xff0c;XR 的接口標準也經歷了混亂到統一的演進過程。從早期的廠商割據&#xff0c;到 Unity 的初步抽象&…

Python基礎教學:航天工程領域的精確計算和金融領域的精確計算,分別采用的小數保留位數的方法有哪些?有什么區別?-由Deepseek產生

在Python中處理航天工程和金融領域的精確計算時&#xff0c;雖然都強調精度&#xff0c;但因目標需求、誤差容忍度和計算性質不同&#xff0c;其小數保留位數的方法和策略存在顯著差異。以下是關鍵方法和區別分析&#xff1a; 一、航天工程領域 核心需求&#xff1a; 物理世界…

機器人玩具:成年人的心靈游樂場與未來前哨

當提及“機器人玩具 ”&#xff0c;許多人腦海中仍會浮現出孩童在游戲墊上擺弄塑料小人的畫面。然而&#xff0c;時代已悄然轉變——那些曾被視為童年專屬的機械伙伴&#xff0c;如今正被越來越多的成年人鄭重捧在手中。這不是一種幼稚的退行&#xff0c;而是一場關于創造力、情…

Spring Cloud LoadBalancer深度解析:官方負載均衡方案遷移指南與避坑實踐

引言&#xff1a;為什么LoadBalancer正在取代Ribbon&#xff1f; “Ribbon已進入維護模式” —— Spring官方公告 當你的Spring Boot升級到3.x版本&#xff0c;Ribbon的依賴項將無法通過編譯。作為Spring Cloud 官方欽定的替代方案&#xff0c;LoadBalancer憑借&#xff1a; ?…

暴雨服務器成功中標洪湖市政府框架采購項目

近日&#xff0c;在洪湖市政府 2025 年度行政事業單位服務器封閉式框架協議采購項目中&#xff0c;暴雨服務器憑借其卓越的性能、優質的服務以及合理的價格&#xff0c;成功脫穎而出&#xff0c;贏得了該項目的中標資格。這一成果不僅標志著暴雨服務器在政府領域的認可度進一步…

C# 多線程按順序執行之ManualResetEvent

ManualResetEvent被用于在** 兩個或多個線程間** 進行線程信號發送。 多個線程可以通過調用ManualResetEvent對象的WaitOne方法進入等待或阻塞狀態。當控制線程調用Set()方法&#xff0c;所有等待線程將恢復并繼續執行。 以下是使用ManualResetEvent的例子&#xff0c;確保多線…

SQL里的正則

1393-capital-gainloss https://leetcode.com/problems/capital-gainloss/description/ IDEA報紅但是能執行&#xff01; -- 用全部賣出的減去全部買入的 with b as ( select stock_name, sum(price) AS total_buy_price from Stocks where operation Buygroup by stock_na…

計算機求職提前批/求職什么時候投遞合適

前言 大家秋招或者春招&#xff0c;可能一直在網上沖浪&#xff0c;看到一些人在鼓吹說提前批開始&#xff0c;秋招開始。必須要趕緊找工作了&#xff0c;再不找就失業了等等。 然后&#xff0c;到自己就開始焦慮&#xff0c;感覺別人都在投簡歷&#xff0c;自己不投感覺很吃虧…

八種數據結構簡介

目錄 1.1 數據結構概述 1.2 數據結構的分類 1.2.1 邏輯結構 1&#xff09;集合 2&#xff09;線性結構 3&#xff09;樹形結構 4&#xff09;圖形結構 1.2.2 物理結構 1&#xff09;順序存儲 2&#xff09;鏈式存儲 3&#xff09;散列存儲 4&#xff09;索引存儲 …

破壁虛實的情感科技革命:元晟定義AI陪伴機器人個性化新紀元

在人工智能席卷全球的浪潮中&#xff0c;廣東中山一家名為元晟傳媒科技的企業正悄然改寫情感陪伴產業的游戲規則。作為廣東元伴智能科技&#xff08;下稱“元伴智能”&#xff09;的戰略級下屬機構&#xff0c;中山元晟傳媒科技憑借獨特的“技術場景流量”三角模型&#xff0c;…

leetcode_455 分餅干

1. 題意 給一堆餅干&#xff0c;和一群小朋友。餅干有大小&#xff0c;小朋友有胃口值&#xff1b;小朋友不吃比自己胃口小的餅干&#xff0c;問這些餅干能滿足多少小朋友食用。 2. 題解 排序貪心 優先用小餅干滿足胃口小的小朋友&#xff0c;這樣大餅干就能留給胃口大的小朋…

使用 C# 源生成器(Source Generators)進行高效開發:增強 Blazor 及其他功能

.NET 中源生成器的引入徹底改變了我們的開發方式&#xff0c;它消除了動態邏輯&#xff0c;并在編譯時生成靜態代碼。這不僅提高了應用程序的性能&#xff0c;還提升了開發人員的生產力和代碼質量。 如果您正在使用Blazor&#xff08;WebAssembly 或服務器&#xff09;或構建需…

word如何插入高清晰的matlab繪圖

emf矢量圖 在matlab中畫好的圖另存為emf格式&#xff0c;保存到本地&#xff0c;然后在word中選擇插圖圖片&#xff0c;注意不要復制粘貼。 親測好用&#xff01;

解鎖 ChatGPT 超能力:全新「記憶」功能深度解析!

點擊下方“JavaEdge”&#xff0c;選擇“設為星標” 第一時間關注技術干貨&#xff01; 免責聲明~ 任何文章不要過度深思&#xff01; 萬事萬物都經不起審視&#xff0c;因為世上沒有同樣的成長環境&#xff0c;也沒有同樣的認知水平&#xff0c;更「沒有適用于所有人的解決方案…

低壓電涌保護:構筑電氣設備的安全防線

在現代電力系統中&#xff0c;低壓電涌保護扮演著至關重要的角色。雷電和電力系統中的瞬態過電壓&#xff0c;是威脅電氣設備安全運行的潛在風險。低壓電涌保護器&#xff08;SPD&#xff09;作為一種專門設計的防護裝置&#xff0c;能夠有效地抑制這些電涌&#xff0c;確保電氣…

GitLab多人協作MR流程規范模版(merge)

以下是一個適用于 GitLab 多人協作的 MR 流程規范模板&#xff0c;涵蓋分支策略、MR 創建流程、沖突處理、審查要求和 CI/CD 設置。可以直接復制到團隊 Wiki 或文檔中使用。 &#x1f4d8; 一、分支策略 main ← 線上生產分支&#xff0c;僅從 release 合并 dev …