【LUT技術專題】CLUT代碼講解

本文是對CLUT技術的代碼講解,原文解讀請看CLUT文章講解。

1、原文概要

CLUT利用矩陣在保持3DLUT映射能力的前提下顯著降低了參數量。整體流程如下所示。
在這里插入圖片描述
整體還是基于3D-LUT的框架,只不過添加了一個壓縮自適應的變換矩陣。作者使用的損失函數在3DLUT的基礎上額外添加了一個余弦相似度的損失。

2、代碼結構

代碼整體結構如下
在這里插入圖片描述
核心代碼是models.py與LUT.py文件。

3 、核心代碼模塊

model.py 文件

1. CLUTNet類

這里是網絡的整體實現,其定義了backbone、classifier、CLUT。

class CLUTNet(nn.Module): def __init__(self, nsw, dim=33, backbone='Backbone', *args, **kwargs):super().__init__()self.TrilinearInterpolation = TrilinearInterpolation()self.pre = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])self.backbone = eval(backbone)()last_channel = self.backbone.last_channelself.classifier = nn.Sequential(nn.Conv2d(last_channel, 128,1,1),nn.Hardswish(inplace=True),nn.Dropout(p=0.2, inplace=True),nn.Conv2d(128, int(nsw[:2]),1,1),)nsw = nsw.split("+")num, s, w = int(nsw[0]), int(nsw[1]), int(nsw[2])self.CLUTs = CLUT(num, dim, s, w)def fuse_basis_to_one(self, img, TVMN=None):mid_results = self.backbone(self.pre(img))weights = self.classifier(mid_results)[:,:,0,0] # n, numD3LUT, tvmn_loss = self.CLUTs(weights, TVMN)return D3LUT, tvmn_loss    def forward(self, img, img_org, TVMN=None):D3LUT, tvmn_loss = self.fuse_basis_to_one(img, TVMN)img_res = self.TrilinearInterpolation(D3LUT, img_org)return {"fakes": img_res + img_org,"3DLUT": D3LUT,"tvmn_loss": tvmn_loss,}

前向中給出了計算過程,首先圖像經過backbone計算中間結果,然后經過classifer得到CLUT的輸入,最后給到CLUT變換得到實際使用的3DLUT。

2. CLUT類

定義了CLUT的計算過程,講解中提到了有3個主要參數,num代表LUT的條數,s和w是壓縮的參數。

class CLUT(nn.Module):def __init__(self, num, dim=33, s="-1", w="-1", *args, **kwargs):super(CLUT, self).__init__()self.num = numself.dim = dimself.s,self.w = s,w = eval(str(s)), eval(str(w))# +: compressed;  -: uncompressedif s == -1 and w == -1: # standard 3DLUTself.mode = '--'self.LUTs = nn.Parameter(torch.zeros(num,3,dim,dim,dim))elif s != -1 and w == -1:  self.mode = '+-'self.s_Layers = nn.Parameter(torch.rand(dim, s)/5-0.1)self.LUTs = nn.Parameter(torch.zeros(s, num*3*dim*dim))elif s == -1 and w != -1: self.mode = '-+'self.w_Layers = nn.Parameter(torch.rand(w, dim*dim)/5-0.1)self.LUTs = nn.Parameter(torch.zeros(num*3*dim, w))else: # full-version CLUTself.mode = '++'self.s_Layers = nn.Parameter(torch.rand(dim, s)/5-0.1)self.w_Layers = nn.Parameter(torch.rand(w, dim*dim)/5-0.1)self.LUTs = nn.Parameter(torch.zeros(s*num*3,w))print("n=%d s=%d w=%d"%(num, s, w), self.mode)def reconstruct_luts(self):dim = self.dimnum = self.numif self.mode == "--":D3LUTs = self.LUTselse:if self.mode == "+-":# d,s  x  s,num*3dd  -> d,num*3dd -> d,num*3,dd -> num,3,d,dd -> num,-1CUBEs = self.s_Layers.mm(self.LUTs).reshape(dim,num*3,dim*dim).permute(1,0,2).reshape(num,3,self.dim,self.dim,self.dim)if self.mode == "-+":# num*3d,w x w,dd -> num*3d,dd -> num,3dddCUBEs = self.LUTs.mm(self.w_Layers).reshape(num,3,self.dim,self.dim,self.dim)if self.mode == "++":# s*num*3, w  x   w, dd -> s*num*3,dd -> s,num*3*dd -> d,num*3*dd -> num,-1CUBEs = self.s_Layers.mm(self.LUTs.mm(self.w_Layers).reshape(-1,num*3*dim*dim)).reshape(dim,num*3,dim**2).permute(1,0,2).reshape(num,3,self.dim,self.dim,self.dim)D3LUTs = cube_to_lut(CUBEs)return D3LUTsdef combine(self, weights, TVMN): # n,numdim = self.dimnum = self.numD3LUTs = self.reconstruct_luts()if TVMN is None:tvmn_loss = 0else:tvmn_loss = TVMN(D3LUTs)D3LUT = weights.mm(D3LUTs.reshape(num,-1)).reshape(-1,3,dim,dim,dim)return D3LUT, tvmn_lossdef forward(self, weights, TVMN=None):lut, tvmn_loss = self.combine(weights, TVMN)return lut, tvmn_loss

mode這里是調整壓縮的模式,當然我們需要的是完全壓縮的版本,即mode==“++”,可以看到首先會對w_layers與self.LUTs矩陣乘,后續在跟s_layers進行矩陣乘,這與講解相對應。

utils/LUT.py 文件

1. cube_to_lut函數

此函數在CLUT類的前向完成處理最后會調用到。

def cube_to_lut(cube): # (n,)3,d,d,dif len(cube.shape) == 5:to_shape = [[0,2,3,1],[0,2,1,3],]else:to_shape = [[1,2,0],[1,0,2],]if isinstance(cube, torch.Tensor):lut = torch.empty_like(cube)lut[...,0,:,:,:] = cube[...,0,:,:,:].permute(*to_shape[0])lut[...,1,:,:,:] = cube[...,1,:,:,:].permute(*to_shape[1])lut[...,2,:,:,:] = cube[...,2,:,:,:]else:lut = np.empty_like(cube)lut[...,0,:,:,:] = cube[...,0,:,:,:].transpose(*to_shape[0])lut[...,1,:,:,:] = cube[...,1,:,:,:].transpose(*to_shape[1])lut[...,2,:,:,:] = cube[...,2,:,:,:]return lut

通過CLUT類我們可以看到送入到該函數的輸入的shape是(num,3,self.dim,self.dim,self.dim),因為shape的長度為5,to_shape是[0,2,3,1]以及[0,2,1,3],也就是說實際的lut是調換通道順序的cube變量。

3、總結

代碼實現核心的部分講解完畢,跟以往最不同的部分就在于這個CLUT的計算矩陣,把這部分看明白就行。


感謝閱讀,歡迎留言或私信,一起探討和交流。
如果對你有幫助的話,也希望可以給博主點一個關注,感謝。

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

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

相關文章

在LinuxMint 22.1(Ubuntu24.04)上安裝使用同花順遠航版

剛剛在LinuxMint 22.1(Ubuntu24.04)安裝完成同花順遠航版,體驗特別好,忍不住要及時給深受Linux平臺無好用行情軟件之苦的朋友們進行分享了。在此之前我一直只能用同花順Linux原生版的行情軟件,但是該軟件只有很基本的行情功能,而且…

解決vue3路由配合Transition時跳轉導致頁面不渲染的問題

問題復現 <router-view v-slot"{ Component, route }"><transition name"fade" mode"out-in"><keep-alive><component :is"Component" :key"route.path" /></keep-alive></transition>…

java: 無法訪問org.springframework.boot.SpringApplication,類文件具有錯誤的版本 61.0, 應為 52.0

問題 java: 無法訪問org.springframework.boot.SpringApplication 錯誤的類文件: /D:/.m2/repository/org/springframework/boot/spring-boot/3.3.13/spring-boot-3.3.13.jar!/org/springframework/boot/SpringApplication.class 類文件具有錯誤的版本 61.0, 應為 52.0 請刪除…

Docker拉取nacos鏡像

以下是使用 Docker 拉取并運行 Nacos&#xff08;阿里巴巴開源的配置中心和服務發現組件&#xff09;鏡像的詳細指南&#xff1a; 1. 拉取 Nacos 官方鏡像 拉取最新版 Nacos 鏡像&#xff08;推薦指定版本以避免兼容性問題&#xff09;&#xff1a; # 拉取最新版本&#xff…

【CTF-Web環境搭建】kali

Kali虛擬機下載 這里在官網上下載下kali虛擬機Get Kali | Kali Linux 網速比較慢的話打開一下加速器 下載完成后 得到一個壓縮包 選擇一個合適的地方將這個壓縮包解壓一下 記住這個文件目錄 這里為了后續方便 簡歷一個叫做Virtual Machines的文件夾 里面就可以放不同的虛擬機…

微服務架構的演進:邁向云原生

微服務架構的演進&#xff1a;邁向云原生ps:最近在學習的時候&#xff0c;發現好多技術方案最終都有云原生的影子&#xff0c;這里淺談一下云原生的發展趨勢隨著互聯網技術的發展&#xff0c;軟件開發模式經歷了從單體應用到微服務架構的重大轉變。而在今天&#xff0c;微服務架…

服務器如何配置防火墻規則開放/關閉端口?

配置服務器防火墻規則&#xff08;開放/關閉端口&#xff09;是服務器安全管理的基礎操作&#xff0c;不同操作系統和防火墻工具的配置方式有所不同。以下是主流系統的詳細操作指南&#xff1a;一、Linux系統&#xff08;iptables/firewalld/UFW&#xff09;1. iptables&#x…

基于SpringBoot+Redis實現外呼頻次限制功能

針對外呼場景中的號碼頻次限制需求&#xff08;如每3天只能呼出1000通電話&#xff09;&#xff0c;我可以提供一個基于Spring Boot和Redis的完整解決方案。 方案設計 核心思路 使用Redis的計數器過期時間機制 采用滑動窗口算法實現精確控制 通過Lua腳本保證原子性操作 實…

下一代 2D 圖像設計工具「GitHub 熱點速覽」

長期以來&#xff0c;2D 設計領域似乎已是 Adobe 與 Figma 的天下&#xff0c;層疊的圖層、熟悉的工具欄&#xff0c;一切都顯得那么順理成章&#xff0c;卻也讓不少設計師在創意的邊界上感到了些許乏力。當我們以為設計工具的革新只能是小修小補時&#xff0c;開源社區再次扮演…

L58.【LeetCode題解】模擬算法習題集1(Z 字形變換、外觀數列)

目錄 1.Z 字形變換 方法1: 模擬 代碼 提交結果 方法2:優化后的模擬 代碼 提交結果 2.外觀數列 方法1:模擬 代碼 提交結果 方法2:打表 知識回顧 代碼 1.Z 字形變換 https://leetcode.cn/problems/zigzag-conversion/ 將一個給定字符串 s 根據給定的行數 numRows &…

Flink MySQL CDC 環境配置與驗證

一、MySQL 服務器配置詳解 1. 啟用二進制日志&#xff08;Binlog&#xff09; MySQL CDC 依賴二進制日志獲取增量數據&#xff0c;需在 MySQL 配置文件&#xff08;my.cnf 或 my.ini&#xff09;中添加以下配置&#xff1a; # 啟用二進制日志 log-binmysql-bin # 二進制日志…

如何查看自己電腦的CUDA版本?

在搜索欄輸入命令提示符 打開 輸入 nvidia-smi圖片中的兩個是CUDA版本和顯卡的信息

opencv使用 GStreamer 硬解碼和 CUDA 加速的方案

在Conda環境中從源代碼編譯OpenCV&#xff08;支持CUDA和GStreamer&#xff09; 以下是完整的方案步驟&#xff0c;包括必要的依賴庫安裝過程&#xff1a; 1. 安裝Miniconda&#xff08;如果尚未安裝&#xff09; # 下載Miniconda安裝腳本 wget https://repo.anaconda.com/m…

Java面試寶典:多線程一

1. run() vs start() 陷阱題 下面程序的運行結果 public static void main(String[] args) {Thread t = new Thread(

【CSS-14-基礎樣式表Base.css】如何編寫高質量的Base.css:前端樣式重置與基礎規范指南

在前端開發中&#xff0c;Base.css&#xff08;也稱為重置樣式表或基礎樣式表&#xff09;是整個項目樣式的基石。它負責消除瀏覽器默認樣式的差異&#xff0c;建立統一的樣式基準&#xff0c;為后續開發提供一致的起點。一個精心設計的Base.css能夠顯著提高開發效率&#xff0…

探索Python數據科學工具鏈NumPyPandas與Scikit-learn

NumPy&#xff1a;數值計算的基石 NumPy是Python中用于科學計算的核心庫&#xff0c;它提供了一個強大的N維數組對象&#xff0c;以及大量的數學函數庫&#xff0c;能夠高效地進行向量和矩陣運算。對于數據科學家而言&#xff0c;掌握NumPy是進行數據處理和算法實現的基礎。 創…

八股學習(三)---MySQL

一、MySQL中的回表是什么&#xff1f;我的回答&#xff1a;MySQL回表指的是在查詢使用非聚簇索引也就是二級索引時&#xff0c;葉子節點只存儲了索引列的值和主鍵Id&#xff0c;若要查詢其他字段&#xff0c;就要根據主鍵去聚簇索引查詢完整的數據。這個過程就是回表。比如用na…

NeighborGeo:基于鄰居的IP地理定位(一)

NeighborGeo:基于neighbors的IP地理定位 X. Wang, D. Zhao, X. Liu, Z. Zhang, T. Zhao, NeighborGeo: IP geolocation based on neighbors, Comput. Netw. 257 (2025) 110896, Abstract IP地址定位在網絡安全、電子商務、社交媒體等領域至關重要。當前主流的圖神經網絡方法…

MySQL 8.0:窗口函數

一、基礎知識 定義 窗口函數&#xff08;Window Function&#xff09;對查詢結果集的子集&#xff08;“窗口”&#xff09;進行計算&#xff0c;保留原始行而非聚合為單行&#xff0c;適合復雜分析&#xff08;如排名、累積和&#xff09;。 基本語法&#xff1a; 函數名() OV…

AI 深度學習面試題學習

1.神經網絡 1.1各個激活函數的優缺點? 1.2為什么ReLU常用于神經網絡的激活函數? 1.在前向傳播和反向傳播過程中,ReLU相比于Sigmoid等激活函數計算量小; 2.避免梯度消失問題。對于深層網絡,Sigmoid函數反向傳播時,很容易就會出現梯度消失問題(在Sigmoid接近飽和區時,變換…