@synthesize obj=_obj的意义详解 @property和@synthesize

我们在进行iOS开发时,经常会在类的声明部分看见类似于@synthesize window=_window; 的语句,那么,这个window是什么,_ window又是什么,两个东西分别怎么用,这是一个比较基本的问题,也关乎我们理解Objective-C中对类、类的属性、类的存取器、类的局部变量的统一理解。
在32位系统中,如果类的 @interface 部分没有进行 ivar 声明,但有 @property 声明,在类的 @implementation 部分有响应的 @synthesize,则会得到类似下面的编译错误:
Synthesized property 'xX' must either be named the same as a compatible ivar or must explicitly name an ivar
在 64-bit时,运行时系统会自动给类添加 ivar,添加的 ivar 以一个下划线"_"做前缀。
上面声明部分的 @synthesize window=_window; 意思是说,window 属性为 _window 实例变量合成访问器方法。
也就是说,window属性生成存取方法是setWindow,这个setWindow方法就是_window变量的存取方法,它操作的就是_window这个变量。通过这个看似是赋值的这样一个操作,我们可以在@synthesize 中定义与变量名不相同的getter和setter的命名,籍此来保护变量不会被不恰当的访问。

下面是一个常见的例子
写法一:
C代码  收藏代码

@interface MyClass:NSObject{    

        MyObjecct *_myObject;  

}  

@property(nonamtic, retain) MyObjecct *myObject;  

@end  

  

@implementatin MyClass  

@synthesize myObject=_myObject;  

 

写法二:
C代码  收藏代码

@interface MyClass:NSObject{  

        

}  

@property(nonamtic, retain) MyObjecct *myObject;  

@end  

  

@implementatin MyClass  

@synthesize myObject=_myObject;  

 
这个类中声明了一个变量_myObject,又声明了一个属性叫myObject,然后用@synthesize生成了属性myObject的存取方法,这个存取方法的名字应该是:setmyObject和getmyObject。@synthesize myObject=_myObject的含义就是属性myObject的存取方法是做用于_myObject这个变量的。这种用法在Apple的Sample Code中很常见。
弄明白了这个语句的意思之后,我们也就清楚了myObject和_myObject的区别,那么,在使用的时候,有什么需要注意的地方,大家应该也都清楚了。是的,myObject是属性,而_ myObject才是变量,我们最终操作的变量都是myObject。
那么,同样是存取操作,语句
C代码  收藏代码

self.nameVarPtr = [[ObjectName alloc] init]   

 
C代码  收藏代码

nameVarPtr = [[ObjectName alloc] init]  

两种赋值方式的区别何在呢?

 

self.nameVarPtr=xxx 这种赋值方式等价于调用 [self setnameVarPtr:xxx], 而setnameVarPtr:xxx的方法的实现又是依赖于@property的属性的,比如retain,assign等属性。


nameVarPtr = xxx 的赋值方式,仅仅是对一个指针进行赋值。nameVarPtr仅仅是一个指针变量,记录了xxx的地址。在这个过程中不会调用setter方法,不会调用setter方法,就和@property没有关系,从而,也和retain,assign等属性没有关系。这种赋值方式就是一个简单的指针赋值。


综上,对成员变量进行赋值,为防内存泄露需要注意的点:

1.self调用setter方法的方式

ObjectName*  tmp= [[ObjectName alloc] init];

self.nameVarPtr =tmp;                 //retainCount=2

[tmp release];                               //retainCount=1


2.指针赋值方式,不会调用setter方法

nameVarPtr= [[ObjectName alloc] init]; // retainCount=1


所以,笔者建议大家在对某个变量进行赋值操作的时候,尽量要写self.myObj = xxx; 这才是最可靠的方法。

@property和@synthesize可以自动生成某个类成员变量的存取方法

readwrite:这个属性是默认的情况,会自动为你生成存取器

assign:这个属性一般用来处理基础类型,比如int、float等等,如果你声明的属性是基础类型的话,assign是默认的,你可以不加这个属性

natomic:默认是有该属性的,这个属性是为了保证程序在多线程情况,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题

readonly:只生成getter不会有setter方法

copy:这个会自动生成你赋值对象的克隆,相当于在内存中新生成了该对象的副本,这样一来,改变赋值对象就不会改变你声明的这个成员变量了

retain:会自动retain赋值对象

nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率

http://blog.youkuaiyun.com/beautifularea/article/details/6886604

 assign:指定setter方法用简单的赋值,这是默认操作。你可以对标量类型(如int)使用这个属性。你可以想象一个float,它不是一个对象,所以它不能retain、copy。

 assign:简单赋值,不更改索引计数(Reference Counting).使用assign: 对基础数据类型 (NSInteger)和C数据类型(int, float, double, char,等)

 retain:指定retain应该在后面的对象上调用,前一个值发送一条release消息。你可以想象一个NSString实例,它是一个对象,而且你可能想要retain它。

 

 retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 ,使用retain: 对其他NSObject和其子类 ,retain,是说明该属性在赋值的时候,先release之前的值,然后再赋新值给属性,引用再加1。

 

 copy:指定应该使用对象的副本(深度复制),前一个值发送一条release消息。基本上像retain,但是没有增加引用计数,是分配一块新的内存来放置它。copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。copy:建立一个索引计数为1的对象,然后释放旧对象,copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。

readonly:将只生成getter方法而不生成setter方法(getter方法没有get前缀)

readwrite:默认属性,将生成不带额外参数的getter和setter方法(setter方法只有一个参数)

atomic:对于对象的默认属性,就是setter/getter生成的方法是一个原子操作。如果有多个线程同时调用setter的话,不会出现某一个线程执行setter全部语句之前,另一个线程开始执行setter的情况,相关于方法头尾加了锁一样。


nonatomic:不保证setter/getter的原子性,多线程情况下数据可能会有问题。nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。先释放原先变量,再将新变量     retain然后赋值;

      注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。

http://blog.sina.com.cn/s/articlelist_1605247797_0_1.html

%% LED光谱合成与优化 - 修正版 % 中央民族大学数学建模竞赛 - 问题2解决方案 % 所有函数定义移至文件末尾 %% 初始化 clear; clc; close all; % 定义波长范围 (380-781nm) wavelengths = 380:1:781; % 402个波长点 % 五通道LED SPD (实际应从Excel导入) % 这里使用模拟数据代替 blue = zeros(402,1); green = zeros(402,1); red = zeros(402,1); ww = zeros(402,1); cw = zeros(402,1); % 创建模拟SPD数据 (高斯分布) for i = 1:402 wl = wavelengths(i); blue(i) = exp(-((wl-450)/20).^2); green(i) = exp(-((wl-540)/25).^2); red(i) = exp(-((wl-620)/15).^2); ww(i) = exp(-((wl-580)/80).^2); cw(i) = exp(-((wl-500)/100).^2); end % 归一化SPD blue = blue / max(blue); green = green / max(green); red = red / max(red); ww = ww / max(ww); cw = cw / max(cw); % 模拟CIE标准函数 cie_x = zeros(402,1); cie_y = zeros(402,1); cie_z = zeros(402,1); mel_sens = zeros(402,1); D65 = zeros(402,1); for i = 1:402 wl = wavelengths(i); cie_x(i) = exp(-((wl-600)/100).^2); cie_y(i) = exp(-((wl-550)/100).^2); cie_z(i) = exp(-((wl-450)/80).^2); mel_sens(i) = exp(-((wl-480)/40).^2); D65(i) = exp(-((wl-550)/150).^2); end %% 优化问题设置 % 边界条件 (权重在0-1之间) lb = [0, 0, 0, 0, 0]; ub = [1, 1, 1, 1, 1]; % 优化选项 options = optimoptions('fmincon', 'Display', 'iter', ... 'Algorithm', 'sqp', 'MaxFunctionEvaluations', 10000); % 初始权重 w0 = [0.2, 0.2, 0.2, 0.2, 0.2]; %% 求解日间照明模式 (最大化Rf) % 调用优化器 [w_opt_day, fval_day] = fmincon(... @(w) obj_func_day(w, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65), ... w0, [], [], [], [], lb, ub, ... @(w) constraints_day(w, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65), ... options); % 计算实际Rf值 spd_day = synthesize_spd(w_opt_day, blue, green, red, ww, cw); [~, rf_day] = calculate_rf_rg(spd_day, D65); rf_day = -fval_day; %% 求解夜间助眠模式 (最小化mel-DER) % 调用优化器 [w_opt_night, mel_der_night] = fmincon(... @(w) obj_func_night(w, blue, green, red, ww, cw, mel_sens, D65), ... w0, [], [], [], [], lb, ub, ... @(w) constraints_night(w, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65), ... options); %% 结果计算与展示 % 计算日间模式所有参数 spd_day = synthesize_spd(w_opt_day, blue, green, red, ww, cw); [X_day, Y_day, Z_day] = calculate_xyz(spd_day, cie_x, cie_y, cie_z); [cct_day, duv_day] = calculate_cct_duv(X_day, Y_day, Z_day); [rf_day, rg_day] = calculate_rf_rg(spd_day, D65); mel_der_day = calculate_mel_der(spd_day, mel_sens, D65); % 计算夜间模式所有参数 spd_night = synthesize_spd(w_opt_night, blue, green, red, ww, cw); [X_night, Y_night, Z_night] = calculate_xyz(spd_night, cie_x, cie_y, cie_z); [cct_night, duv_night] = calculate_cct_duv(X_night, Y_night, Z_night); [rf_night, rg_night] = calculate_rf_rg(spd_night, D65); mel_der_night = calculate_mel_der(spd_night, mel_sens, D65); % 显示结果 fprintf('\n===== 日间照明模式最优解 =====\n'); fprintf('权重: 蓝光=%.4f, 绿光=%.4f, 红光=%.4f\n', w_opt_day(1), w_opt_day(2), w_opt_day(3)); fprintf(' 暖白光=%.4f, 冷白光=%.4f\n', w_opt_day(4), w_opt_day(5)); fprintf('CCT: %.0f K, Duv: %.4f\n', cct_day, duv_day); fprintf('Rf: %.1f, Rg: %.1f\n', rf_day, rg_day); fprintf('mel-DER: %.3f\n\n', mel_der_day); fprintf('===== 夜间助眠模式最优解 =====\n'); fprintf('权重: 蓝光=%.4f, 绿光=%.4f, 红光=%.4f\n', w_opt_night(1), w_opt_night(2), w_opt_night(3)); fprintf(' 暖白光=%.4f, 冷白光=%.4f\n', w_opt_night(4), w_opt_night(5)); fprintf('CCT: %.0f K, Duv: %.4f\n', cct_night, duv_night); fprintf('Rf: %.1f, Rg: %.1f\n', rf_night, rg_night); fprintf('mel-DER: %.3f\n', mel_der_night); %% 光谱可视化 figure('Position', [100, 100, 1200, 500]); % 日间模式光谱 subplot(1, 2, 1); plot(wavelengths, spd_day/max(spd_day), 'b', 'LineWidth', 2); hold on; plot(wavelengths, mel_sens/max(mel_sens), 'g--', 'LineWidth', 1.5); title('日间照明模式光谱'); xlabel('波长 (nm)'); ylabel('归一化强度'); legend('合成光谱', '视黑素灵敏度', 'Location', 'northeast'); grid on; xlim([380, 780]); % 夜间模式光谱 subplot(1, 2, 2); plot(wavelengths, spd_night/max(spd_night), 'r', 'LineWidth', 2); hold on; plot(wavelengths, mel_sens/max(mel_sens), 'g--', 'LineWidth', 1.5); title('夜间助眠模式光谱'); xlabel('波长 (nm)'); ylabel('归一化强度'); legend('合成光谱', '视黑素灵敏度', 'Location', 'northeast'); grid on; xlim([380, 780]); %% 权重分布图 figure(); labels = {'蓝光', '绿光', '红光', '暖白光', '冷白光'}; subplot(1, 2, 1); bar(w_opt_day); set(gca, 'XTickLabel', labels); title('日间模式权重分布'); ylabel('权重系数'); ylim([0, 1]); subplot(1, 2, 2); bar(w_opt_night); set(gca, 'XTickLabel', labels); title('夜间模式权重分布'); ylabel('权重系数'); ylim([0, 1]); %% ==================== 函数定义区域 ==================== % 以下为所有函数定义,确保位于文件末尾 function spd = synthesize_spd(weights, blue, green, red, ww, cw) % 合成五通道光谱 w_b = weights(1); w_g = weights(2); w_r = weights(3); w_ww = weights(4); w_cw = weights(5); spd = w_b*blue + w_g*green + w_r*red + w_ww*ww + w_cw*cw; end function [X, Y, Z] = calculate_xyz(spd, cie_x, cie_y, cie_z) % 计算CIE XYZ三刺激值 X = sum(spd .* cie_x); Y = sum(spd .* cie_y); Z = sum(spd .* cie_z); end function [cct, duv] = calculate_cct_duv(X, Y, Z) % 计算相关色温(CCT)Duv % 转换到CIE 1960 UCS空间 u = 4*X / (X + 15*Y + 3*Z); v = 6*Y / (X + 15*Y + 3*Z); % 简化计算 - 实际应使用普朗克轨迹插值 % 这里使用近似公式 n = (X - 0.3320*Y - 0.0038*Z) / (0.0037*Y - 0.0011*Z); cct = 437*n^3 + 3601*n^2 + 6861*n + 5517; duv = sqrt((u - 0.2)^2 + (v - 0.3)^2); % 示例计算 end function [rf, rg] = calculate_rf_rg(spd, ref_spd) % 简化版显色指数计算 % 这里使用色差模拟 diff = mean(abs(spd - ref_spd)); rf = 90 - 15*diff; % Rf在75-95之间 rg = 95 - 10*diff; % Rg在85-105之间 end function mel_der = calculate_mel_der(spd, mel_sens, D65) % 计算褪黑素日光效率比 mel_flux = sum(spd .* mel_sens); d65_mel = sum(D65 .* mel_sens); mel_der = mel_flux / d65_mel; end function f = obj_func_day(weights, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65) % 日间模式目标函数:最大化Rf spd = synthesize_spd(weights, blue, green, red, ww, cw); rf = calculate_rf_rg(spd, D65); f = -rf; % 最大化Rf = 最小化 -Rf end function [c, ceq] = constraints_day(weights, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65) % 日间模式约束条件 spd = synthesize_spd(weights, blue, green, red, ww, cw); [X, Y, Z] = calculate_xyz(spd, cie_x, cie_y, cie_z); [cct, ~] = calculate_cct_duv(X, Y, Z); [rf, rg] = calculate_rf_rg(spd, D65); % 约束条件: % CCT在5500-6500K, Rg在95-105 c1 = 5500 - cct; % cct >= 5500 c2 = cct - 6500; % cct <= 6500 c3 = 95 - rg; % rg >= 95 c4 = rg - 105; % rg <= 105 ceq = []; % 无等式约束 c = [c1; c2; c3; c4]; % 非线性不等式约束 (需要c<=0) end function f = obj_func_night(weights, blue, green, red, ww, cw, mel_sens, D65) % 夜间模式目标函数:最小化mel-DER spd = synthesize_spd(weights, blue, green, red, ww, cw); f = calculate_mel_der(spd, mel_sens, D65); end function [c, ceq] = constraints_night(weights, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65) % 夜间模式约束条件 spd = synthesize_spd(weights, blue, green, red, ww, cw); [X, Y, Z] = calculate_xyz(spd, cie_x, cie_y, cie_z); [cct, ~] = calculate_cct_duv(X, Y, Z); [rf, ~] = calculate_rf_rg(spd, D65); % 约束条件: % CCT在2500-3500K, Rf>=80 c1 = 2500 - cct; % cct >= 2500 c2 = cct - 3500; % cct <= 3500 c3 = 80 - rf; % rf >= 80 ceq = []; % 无等式约束 c = [c1; c2; c3]; % 非线性不等式约束 (需要c<=0) end 上述代码哪些位置可以加入真实数据,请详细列举出来,并且给我加入真实数据的方法
最新发布
08-23
import os import numpy as np import pandas as pd from scipy.interpolate import interp1d from scipy.optimize import minimize from pymoo.algorithms.soo.nonconvex.ga import GA from pymoo.core.problem import Problem from pymoo.optimize import minimize as pymoo_minimize from pymoo.operators.crossover.sbx import SBX from pymoo.operators.mutation.pm import PM from pymoo.operators.sampling.rnd import FloatRandomSampling import matplotlib.pyplot as plt # ==================== 数据加载 ==================== def load_data(): """加载所有必需数据文件""" base_dir = os.path.dirname(os.path.abspath(__file__)) # 1. 加载五通道LED数据 led_spd = pd.read_excel(os.path.join(base_dir, "附录.xlsx"), sheet_name="Problem 2_LED_SPD") wavelengths = led_spd.iloc[:, 0].values channels = { 'Blue': led_spd.iloc[:, 1].values, 'Green': led_spd.iloc[:, 2].values, 'Red': led_spd.iloc[:, 3].values, 'WarmWhite': led_spd.iloc[:, 4].values, 'ColdWhite': led_spd.iloc[:, 5].values } # 2. 加载CIE标准数据 xyz_data = np.loadtxt(os.path.join(base_dir, "CIE_xyz_1931_2deg.csv"), delimiter=',') d65_data = np.loadtxt(os.path.join(base_dir, "CIE_std_illum_D65.csv"), delimiter=',') test_colors = np.loadtxt(os.path.join(base_dir, "CIE_srf_cfi_1nm.csv"), delimiter=',') return wavelengths, channels, xyz_data, d65_data, test_colors # ==================== 核心计算类 ==================== class LEDOptimizer: def __init__(self, wavelengths, channels, xyz_data, d65_data, test_colors): self.wavelengths = wavelengths self.channels = channels self.channel_names = list(channels.keys()) # 处理CIE标准数据 self.xyz_wl, self.x_bar, self.y_bar, self.z_bar = xyz_data[:,0], xyz_data[:,1], xyz_data[:,2], xyz_data[:,3] self.d65_wl, self.d65_power = d65_data[:,0], d65_data[:,1] self.test_wl, self.test_spectra = test_colors[:,0], test_colors[:,1:100].T # 对齐数据到LED波长范围 self.d65 = interp1d(self.d65_wl, self.d65_power, bounds_error=False, fill_value=0)(self.wavelengths) self.test_spectra = np.array([ interp1d(self.test_wl, s, bounds_error=False, fill_value=0)(self.wavelengths) for s in self.test_spectra ]) def synthesize_spd(self, weights): """合成光谱""" return sum(w * data for w, data in zip(weights, self.channels.values())) def calculate_metrics(self, weights): """计算所有关键指标""" spd = self.synthesize_spd(weights) # 计算XYZ X = np.trapz(spd * self.x_bar, self.wavelengths) Y = np.trapz(spd * self.y_bar, self.wavelengths) Z = np.trapz(spd * self.z_bar, self.wavelengths) if Y > 1e-6: X, Y, Z = 100*X/Y, 100, 100*Z/Y # 计算CCT (简化Robertson方法) x, y = X/(X+Y+Z), Y/(X+Y+Z) n = (x-0.3320)/(y-0.1858) cct = -437*n**3 + 3601*n**2 - 6861*n + 5514.31 # 计算Duv (简化版) denom = X + 15*Y + 3*Z u, v = 4*X/denom, 6*Y/denom duv = 0.003 if cct > 5000 else -0.002 # 简化计算 # 计算Rf/Rg (简化版) delta_E = np.mean(np.abs(spd - self.d65)) # 简化色差计算 Rf = 100 - 4.6 * delta_E Rg = 100 # 简化假设 # 计算mel-DER (简化版) mel_der = np.trapz(spd * (self.wavelengths < 480), self.wavelengths) / \ np.trapz(self.d65 * (self.wavelengths < 480), self.wavelengths) return { 'CCT': cct, 'Duv': duv, 'Rf': Rf, 'Rg': Rg, 'melDER': mel_der, 'SPD': spd } # ==================== 优化问题定义 ==================== class LEDProblem(Problem): def __init__(self, optimizer, mode='day'): self.optimizer = optimizer self.mode = mode n_constr = 4 if mode == 'day' else 3 super().__init__(n_var=5, n_obj=1, n_constr=n_constr, xl=0, xu=1) def _evaluate(self, weights, out, *args, **kwargs): weights = weights / np.sum(weights, axis=1)[:, None] F = np.zeros(weights.shape[0]) G = np.zeros((weights.shape[0], self.n_constr)) for i, w in enumerate(weights): m = self.optimizer.calculate_metrics(w) if self.mode == 'day': F[i] = -m['Rf'] # 最大化Rf G[i,0] = m['CCT'] - 6500 G[i,1] = 5500 - m['CCT'] G[i,2] = 95 - m['Rg'] G[i,3] = m['Rg'] - 105 else: F[i] = m['melDER'] # 最小化melDER G[i,0] = m['CCT'] - 3500 G[i,1] = 2500 - m['CCT'] G[i,2] = 80 - m['Rf'] out["F"] = F out["G"] = G # ==================== 优化执行 ==================== def optimize_led(mode): print(f"\n优化{mode}模式...") data = load_data() optimizer = LEDOptimizer(*data) res = pymoo_minimize( LEDProblem(optimizer, mode), GA(pop_size=30, crossover=SBX(), mutation=PM()), ('n_gen', 30), verbose=False ) weights = res.X / sum(res.X) metrics = optimizer.calculate_metrics(weights) print("\n最优权重:") for name, w in zip(optimizer.channel_names, weights): print(f"{name}: {w:.3f}") print("\n性能指标:") for k, v in metrics.items(): if k != 'SPD': print(f"{k}: {v:.3f}") plt.plot(optimizer.wavelengths, metrics['SPD']) plt.title(f"{mode}模式光谱") plt.xlabel("波长(nm)") plt.ylabel("强度") plt.show() return weights, metrics # ==================== 主程序 ==================== if __name__ == "__main__": day_weights, day_metrics = optimize_led('day') night_weights, night_metrics = optimize_led('night')智能检查这个代码,能正确运行
08-11
# 从文件加载CIE 1931 XYZ色匹配函数数据 def load_cie_xyz_data(file_path): try: data = np.loadtxt(file_path, delimiter=",") wavelengths = data[:, 0] x = data[:, 1] y = data[:, 2] z = data[:, 3] return wavelengths, x, y, z except Exception as e: print(f"Error loading CIE XYZ data: {e}") raise # 从文件加载D65光源数据 def load_d65_data(file_path): try: data = np.loadtxt(file_path, delimiter=",") wavelengths = data[:, 0] power = data[:, 1] return wavelengths, power except Exception as e: print(f"Error loading D65 data: {e}") raise # 构建melanopic spectral sensitivity def build_melanopic_spectral_sensitivity(xyz_wavelengths, x, y, z, target_wavelengths): S = -0.142 * x + 1.793 * y - 0.651 * z M = -0.321 * x + 1.746 * y + 0.575 * z L = 2.003 * x - 0.949 * y - 0.054 * z S /= np.max(S) if np.max(S) != 0 else 1 M /= np.max(M) if np.max(M) != 0 else 1 L /= np.max(L) if np.max(L) != 0 else 1 melanopic_response = 0.238 * S + 0.010 * M + 0.752 * L f = interp1d(xyz_wavelengths, melanopic_response, kind='linear', bounds_error=False, fill_value=0) mel_response = f(target_wavelengths) mel_response /= np.max(mel_response) if np.max(mel_response) != 0 else 1 return mel_response # 加载并预处理所有数据 def load_and_preprocess_data(): current_dir = os.path.dirname(os.path.abspath(__file__)) # 1. 读取SPD数据 spd_df = pd.read_excel(os.path.join(current_dir, "附录.xlsx"), sheet_name="Problem 1") spd_wavelengths = spd_df["波长"].values spd_power = spd_df["光强"].values assert len(spd_wavelengths) == 401, "SPD数据应为380-780nm(401个点)" spd_shape = SpectralShape(spd_wavelengths[0], spd_wavelengths[-1], 1) # 2. 读取XYZ数据 xyz_path = os.path.join(current_dir, "CIE_xyz_1931_2deg.csv") xyz_wavelengths, x_bar, y_bar, z_bar = load_cie_xyz_data(xyz_path) # 插值到SPD波长 f_x = interp1d(xyz_wavelengths, x_bar, kind='linear', bounds_error=False, fill_value=0) f_y = interp1d(xyz_wavelengths, y_bar, kind='linear', bounds_error=False, fill_value=0) f_z = interp1d(xyz_wavelengths, z_bar, kind='linear', bounds_error=False, fill_value=0) x_bar_spd = f_x(spd_wavelengths) y_bar_spd = f_y(spd_wavelengths) z_bar_spd = f_z(spd_wavelengths) # 构建CMF数据结构 cmfs = colour.MultiSpectralDistributions( data=np.column_stack([x_bar_spd, y_bar_spd, z_bar_spd]), wavelengths=spd_wavelengths, labels=['x', 'y', 'z'] ) # 3. 读取D65光源数据 d65_path = os.path.join(current_dir, "CIE_std_illum_D65.csv") d65_wavelengths, d65_power = load_d65_data(d65_path) f_d65 = interp1d(d65_wavelengths, d65_power, kind='linear', bounds_error=False, fill_value=0) d65_power_spd = f_d65(spd_wavelengths) # 4. 读取测试色数据并修正反射率范围 test_color_path = os.path.join(current_dir, "CIE_srf_cfi_1nm.csv") mel_data = np.loadtxt(test_color_path, delimiter=",") assert mel_data.shape[1] == 100, "CIE_srf_cfi_1nm.csv应为100列" test_color_wl = mel_data[:, 0] test_color_spectra = mel_data[:, 1:100].T # 修正:反射率限制在[0,1]物理范围内 test_color_spectra_aligned = np.array([ np.clip(np.interp(spd_wavelengths, test_color_wl, spectrum, left=0, right=0), 0, 1) for spectrum in test_color_spectra ]) # 5. 构建melanopic响应 mel_response = build_melanopic_spectral_sensitivity( xyz_wavelengths, x_bar, y_bar, z_bar, spd_wavelengths ) melanopic_spd = SpectralDistribution(mel_response, spd_wavelengths) return (spd_wavelengths, spd_power, cmfs, d65_power_spd, melanopic_spd, test_color_spectra_aligned, spd_shape, xyz_wavelengths, x_bar, y_bar, z_bar) # 计算XYZ三刺激值 def calculate_xyz(spd_power, cmfs, wavelengths, spd_shape, xyz_wavelengths, x_bar, y_bar, z_bar): power_interp = np.interp(xyz_wavelengths, wavelengths, spd_power, left=0, right=0) y_integral = np.trapz(power_interp * y_bar, xyz_wavelengths) k = 100 / y_integral if y_integral > 1e-9 else 1 manual_x = k * np.trapz(power_interp * x_bar, xyz_wavelengths) manual_y = k * np.trapz(power_interp * y_bar, xyz_wavelengths) manual_z = k * np.trapz(power_interp * z_bar, xyz_wavelengths) return np.array([manual_x, manual_y, manual_z]) # 计算TM30-20的RfRg def calculate_tm30_rf_rg(test_spd, ref_spd, cmfs, wavelengths, test_spectra, spd_shape): def get_cam_values(spd): cam_list = [] for ref_spectrum in test_spectra: ref_spectrum_clipped = np.clip(ref_spectrum, 0, 1) color_spd = spd * ref_spectrum_clipped XYZ = sd_to_XYZ( SpectralDistribution(color_spd, wavelengths), cmfs=cmfs, illuminant=sd_ones(spd_shape) ) XYZ = np.clip(XYZ, 1e-9, None) d65_xyz = sd_to_XYZ( SpectralDistribution(ref_spd, wavelengths), cmfs=cmfs, illuminant=sd_ones(spd_shape) ) d65_xyz = np.clip(d65_xyz, 1e-9, None) cam = XYZ_to_CIECAM02( XYZ / XYZ[1], XYZ_w=d65_xyz / d65_xyz[1], L_A=318.3, Y_b=20, surround=colour.VIEWING_CONDITIONS_CIECAM02['Average'] ) cam_list.append([cam.h, cam.J, cam.C]) return np.array(cam_list) test_cam = get_cam_values(test_spd) ref_cam = get_cam_values(ref_spd) valid_mask = np.logical_and( np.isfinite(test_cam).all(axis=1), np.isfinite(ref_cam).all(axis=1) ) test_cam = test_cam[valid_mask] ref_cam = ref_cam[valid_mask] if len(test_cam) < 50: return 70.0, 100.0 delta_E = np.sqrt( (test_cam[:, 1] - ref_cam[:, 1])**2 + (test_cam[:, 2] - ref_cam[:, 2])**2 + (2 * np.sqrt(test_cam[:, 2] * ref_cam[:, 2]) * np.sin(np.radians((test_cam[:, 0] - ref_cam[:, 0])/2)))**2 ) delta_E = delta_E[delta_E < np.percentile(delta_E, 95)] Rf = np.clip(100 - 4.6 * np.mean(delta_E), 0, 99) def get_gamut_area(cam_data): h = np.arctan2(np.sin(np.radians(cam_data[:, 0])), np.cos(np.radians(cam_data[:, 0]))) * 180/np.pi h = (h + 360) % 360 bins = np.linspace(0, 360, 17) bin_indices = np.digitize(h, bins) - 1 avg_coords = [] for i in range(16): mask = (bin_indices == i) if np.any(mask): avg_j = np.mean(cam_data[mask, 1]) avg_c = np.mean(cam_data[mask, 2]) avg_h = np.mean(cam_data[mask, 0]) avg_coords.append([avg_j, avg_c, avg_h]) if len(avg_coords) < 3: return 0 avg_coords = np.array(avg_coords) x = avg_coords[:, 1] * np.cos(np.radians(avg_coords[:, 2])) y = avg_coords[:, 1] * np.sin(np.radians(avg_coords[:, 2])) return ConvexHull(tstack([x, y])).volume test_area = get_gamut_area(test_cam) ref_area = get_gamut_area(ref_cam) Rg = np.clip(100 * (test_area / ref_area) if ref_area > 1e-9 else 100, 50, 130) return round(Rf, 1), round(Rg, 1) # 计算mel-DER def calculate_mel_der(spd_power, d65_power, mel_response, wavelengths): valid_mask = (wavelengths >= 380) & (wavelengths <= 780) spd_integral = np.trapz( spd_power[valid_mask] * mel_response[valid_mask], wavelengths[valid_mask] ) d65_integral = np.trapz( d65_power[valid_mask] * mel_response[valid_mask], wavelengths[valid_mask] ) if d65_integral < 1e-9: return 0.0 mel_der = spd_integral / d65_integral return round(np.clip(mel_der, 0.01, 1.0), 3) # 计算Duv(最小距离法) def distance_to_planckian(duv, u, v, cct): if cct <= 7000: u0 = (0.860117757 + 1.54118254e-4*cct + 1.28641212e-7*cct**2) / \ (1 + 8.42420235e-4*cct + 7.08145163e-7*cct**2) v0 = (0.317398726 + 4.22806245e-5*cct + 4.20481691e-8*cct**2) / \ (1 - 2.89741816e-5*cct + 1.61456053e-7*cct**2) else: u0 = (0.821943765 + 1.48709244e-4*cct - 5.40467925e-8*cct**2) / \ (1 + 9.44518690e-4*cct + 1.28785040e-6*cct**2) v0 = (0.321018255 + 5.38541694e-5*cct - 3.11079934e-8*cct**2) / \ (1 + 6.83568563e-5*cct + 5.47466662e-8*cct**2) return np.sqrt((u - u0)**2 + (v - (v0 + duv))**2) # 主函数 def calculate_parameters(): (spd_wl, spd_power, cmfs, d65_power, melanopic_spd, test_spectra, spd_shape, xyz_wavelengths, x_bar, y_bar, z_bar) = load_and_preprocess_data() # 计算XYZ三刺激值 XYZ = calculate_xyz(spd_power, cmfs, spd_wl, spd_shape, xyz_wavelengths, x_bar, y_bar, z_bar) X, Y, Z = XYZ # 计算CIE 1960 UCS色坐标(u, v) denom = X + 15 * Y + 3 * Z u = 4 * X / denom if denom != 0 else 0 v = 6 * Y / denom if denom != 0 else 0 # 计算相关色温CCT xy_sum = X + Y + Z x = X / xy_sum if xy_sum != 0 else 0 y = Y / xy_sum if xy_sum != 0 else 0 n = (x - 0.3320) / (y - 0.1858) if (y - 0.1858) != 0 else 0 cct = -437 * n**3 + 3601 * n**2 - 6861 * n + 5514.31 cct = round(np.clip(cct, 1000, 20000), 1) # 计算Duv res = minimize_scalar(lambda d: distance_to_planckian(d, u, v, cct), bounds=(-0.05, 0.05), method='bounded') duv = res.x if v < (0.317398726 + 4.22806245e-5 * cct + 4.20481691e-8 * cct**2) / (1 - 2.89741816e-5 * cct + 1.61456053e-7 * cct**2): duv = -duv duv = round(np.clip(duv, -0.054, 0.054), 4) # 计算Rf、Rg rf, rg = calculate_tm30_rf_rg( test_spd=spd_power, ref_spd=d65_power, cmfs=cmfs, wavelengths=spd_wl, test_spectra=test_spectra, spd_shape=spd_shape ) # 计算mel-DER mel_der = calculate_mel_der( spd_power=spd_power, d65_power=d65_power, mel_response=melanopic_spd.values, wavelengths=spd_wl ) # 输出结果 print("===== 计算结果 =====") print(f"CIE XYZ三刺激值: X={X:.2f}, Y={Y:.2f}, Z={Z:.2f}") print(f"CIE 1960 UCS色坐标: u={u:.4f}, v={v:.4f}") print(f"相关色温 (CCT): {cct} K") print(f"普朗克轨迹距离 (Duv): {duv}") print(f"保真度指数 (Rf, TM30-20): {rf}") print(f"色域指数 (Rg, TM30-20): {rg}") print(f"褪黑素日光照度比 (mel-DER): {mel_der}") if __name__ == "__main__": calculate_parameters()这是我解决问题一的部分代码,刚让你检查的是问题二的代码,所有的参数计算都还按照问题一中的来,不要简化,问题而就是在这些计算方法上多了一个优化
08-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值