此只记录伽马变换原理及其应用结果(文章所有内容基于数字图像处理-冈萨雷斯),和直接用MATLAB代码生成伽马变换代码。
一、原理
伽马变换的公式很简答 就是一个有规律的幂运算 公式如下:
一般在图像中进行应用是 C=1 y为不同值时r的输出曲线,曲线如下:
二、应用场景
在图像处理中 伽马变换都是基于灰度图像来的 其应用的方式有两种,如上图的输出曲线,第一种是增大灰度级,第二种是压缩灰度级,其分界点是y==1。
2.1 增大灰度级
当图整体比较暗,很难观测到细节时,就需要增大灰度级,来增强对比度,让图像的细节更明显,如下图:
上图中 第一幅图是原图,第二幅图是y==0.6,第三幅图是y==0.4,第四幅图是y==0.3,由上图观察可以发现:
红圈:当伽马值从0.6降至04时,会出现更多的细节。将伽马值进一步减小到0.3,会增强背景中的更多细节。
蓝圈:当伽马值==0.3时,开始具有轻微“苍白”外观(尤其是在背景中)的图像相比,对比度开始下降。y=0.4时,对比度和可分辨细节的增强效果最好。y=0.3是一个近似的极限值,低于这个值时,这幅图像的对比度会降低到不可接受的水平。
因此书中给予增强细节的最佳值应为y==0.4;
2.2 压缩灰度级
当图像比较亮,致使整个图片呈现出苍白的画面时,就需要压缩灰度级让图片更加清晰,以显现出更多细节,如下图:
上图中 第一幅图是原图,第二幅图是y==3,第三幅图是y==4,第四幅图是y==5,由上图观察可以发现,使用伽马值3.0和 4.0得到了合适的结果。后一结果的外观更吸引人,因为它的对比度更高。y= 5.0时的结果同样如此。在d图中,靠近图像中间的机场跑道看起来要比其他三幅图像更清晰,但是这个值并不是越大越好,而是有一个自己认为比较合适的值,这个需要自己去调试,个人一般用Y==4这个值,即不会很苍白,细节同样也具备。
三、MATLAB 代码
用MATLAB 代码来实现伽马变换很简单 ,就是做一个幂运算,做完运算后按照特定的方式创建一个verilog代码,并将其输出,就得到一个完整的verilog伽马运算了。
% 伽马变换参数
gamma_value = 0.4; % 固定伽马值
% 创建输入值范围 (0-255)
input_values = 0:255;
% 应用伽马变换公式: output = 255 * (input/255)^gamma
normalized_input = input_values / 255;
output_values = 255 * (normalized_input .^ gamma_value);
% 将输出值四舍五入到最接近的整数并限制在0-255范围内
output_values = round(output_values);
output_values(output_values > 255) = 255;
output_values(output_values < 0) = 0;
% 创建Verilog模块代码
verilog_module = 'module gamma (';
verilog_module = [verilog_module, sprintf('\n input clk ,')];
verilog_module = [verilog_module, sprintf('\n input pre_vsync ,')];
verilog_module = [verilog_module, sprintf('\n input pre_href ,')];
verilog_module = [verilog_module, sprintf('\n input [ 7:0] pre_data ,')];
verilog_module = [verilog_module, sprintf('\n output reg post_vsync ,')];
verilog_module = [verilog_module, sprintf('\n output reg post_href ,')];
verilog_module = [verilog_module, sprintf('\n output reg [ 7:0] post_data ')];
verilog_module = [verilog_module, sprintf('\n);')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\nalways @(posedge clk) begin post_vsync<=pre_vsync; post_href<=pre_href; end')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\nalways @(posedge clk) begin')];
verilog_module = [verilog_module, sprintf('\n case (pre_data)')];
% 添加所有case语句
for i = 0:255
verilog_module = [verilog_module, sprintf('\n 8''d%d: post_data = 8''d%d;', i, output_values(i+1))];
end
% 添加默认case和结束语句
verilog_module = [verilog_module, sprintf('\n default: post_data = 8''d0;')];
verilog_module = [verilog_module, sprintf('\n endcase')];
verilog_module = [verilog_module, sprintf('\nend')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\n')];
verilog_module = [verilog_module, sprintf('\nendmodule')];
% 将Verilog模块保存到文件
filename = 'C:\Users\17353\Desktop\gamma\gamma_lut.v';
fid = fopen(filename, 'w');
if fid == -1
error('无法创建文件');
end
% 直接写入文件
fprintf(fid, '%s', verilog_module);
fclose(fid);
disp(['伽马变换模块已保存到文件: ', filename]);
disp(['伽马值: ', num2str(gamma_value)]);
% 显示部分查找表内容
disp('部分查找表示例:');
for i = [0, 64, 128, 192, 255]
fprintf('输入: %3d -> 输出: %3d\n', i, output_values(i+1));
end
四、MATLAB 生成的verilog 代码
module gamma_lut (
input clk ,
input pre_vsync ,
input pre_href ,
input [ 7:0] pre_data ,
output reg post_vsync ,
output reg post_href ,
output reg [ 7:0] post_data
);
always @(posedge clk) begin post_vsync<=pre_vsync; post_href<=pre_href; end
always @(posedge clk) begin
case (pre_data)
8'd0: post_data = 8'd0;
8'd1: post_data = 8'd28;
8'd2: post_data = 8'd37;
8'd3: post_data = 8'd43;
8'd4: post_data = 8'd48;
8'd5: post_data = 8'd53;
8'd6: post_data = 8'd57;
8'd7: post_data = 8'd61;
8'd8: post_data = 8'd64;
8'd9: post_data = 8'd67;
8'd10: post_data = 8'd70;
8'd11: post_data = 8'd73;
8'd12: post_data = 8'd75;
8'd13: post_data = 8'd78;
8'd14: post_data = 8'd80;
8'd15: post_data = 8'd82;
8'd16: post_data = 8'd84;
8'd17: post_data = 8'd86;
8'd18: post_data = 8'd88;
8'd19: post_data = 8'd90;
8'd20: post_data = 8'd92;
8'd21: post_data = 8'd94;
8'd22: post_data = 8'd96;
8'd23: post_data = 8'd97;
8'd24: post_data = 8'd99;
8'd25: post_data = 8'd101;
8'd26: post_data = 8'd102;
8'd27: post_data = 8'd104;
8'd28: post_data = 8'd105;
8'd29: post_data = 8'd107;
8'd30: post_data = 8'd108;
8'd31: post_data = 8'd110;
8'd32: post_data = 8'd111;
8'd33: post_data = 8'd113;
8'd34: post_data = 8'd114;
8'd35: post_data = 8'd115;
8'd36: post_data = 8'd117;
8'd37: post_data = 8'd118;
8'd38: post_data = 8'd119;
8'd39: post_data = 8'd120;
8'd40: post_data = 8'd122;
8'd41: post_data = 8'd123;
8'd42: post_data = 8'd124;
8'd43: post_data = 8'd125;
8'd44: post_data = 8'd126;
8'd45: post_data = 8'd127;
8'd46: post_data = 8'd129;
8'd47: post_data = 8'd130;
8'd48: post_data = 8'd131;
8'd49: post_data = 8'd132;
8'd50: post_data = 8'd133;
8'd51: post_data = 8'd134;
8'd52: post_data = 8'd135;
8'd53: post_data = 8'd136;
8'd54: post_data = 8'd137;
8'd55: post_data = 8'd138;
8'd56: post_data = 8'd139;
8'd57: post_data = 8'd140;
8'd58: post_data = 8'd141;
8'd59: post_data = 8'd142;
8'd60: post_data = 8'd143;
8'd61: post_data = 8'd144;
8'd62: post_data = 8'd145;
8'd63: post_data = 8'd146;
8'd64: post_data = 8'd147;
8'd65: post_data = 8'd148;
8'd66: post_data = 8'd149;
8'd67: post_data = 8'd149;
8'd68: post_data = 8'd150;
8'd69: post_data = 8'd151;
8'd70: post_data = 8'd152;
8'd71: post_data = 8'd153;
8'd72: post_data = 8'd154;
8'd73: post_data = 8'd155;
8'd74: post_data = 8'd155;
8'd75: post_data = 8'd156;
8'd76: post_data = 8'd157;
8'd77: post_data = 8'd158;
8'd78: post_data = 8'd159;
8'd79: post_data = 8'd160;
8'd80: post_data = 8'd160;
8'd81: post_data = 8'd161;
8'd82: post_data = 8'd162;
8'd83: post_data = 8'd163;
8'd84: post_data = 8'd164;
8'd85: post_data = 8'd164;
8'd86: post_data = 8'd165;
8'd87: post_data = 8'd166;
8'd88: post_data = 8'd167;
8'd89: post_data = 8'd167;
8'd90: post_data = 8'd168;
8'd91: post_data = 8'd169;
8'd92: post_data = 8'd170;
8'd93: post_data = 8'd170;
8'd94: post_data = 8'd171;
8'd95: post_data = 8'd172;
8'd96: post_data = 8'd173;
8'd97: post_data = 8'd173;
8'd98: post_data = 8'd174;
8'd99: post_data = 8'd175;
8'd100: post_data = 8'd175;
8'd101: post_data = 8'd176;
8'd102: post_data = 8'd177;
8'd103: post_data = 8'd177;
8'd104: post_data = 8'd178;
8'd105: post_data = 8'd179;
8'd106: post_data = 8'd179;
8'd107: post_data = 8'd180;
8'd108: post_data = 8'd181;
8'd109: post_data = 8'd182;
8'd110: post_data = 8'd182;
8'd111: post_data = 8'd183;
8'd112: post_data = 8'd183;
8'd113: post_data = 8'd184;
8'd114: post_data = 8'd185;
8'd115: post_data = 8'd185;
8'd116: post_data = 8'd186;
8'd117: post_data = 8'd187;
8'd118: post_data = 8'd187;
8'd119: post_data = 8'd188;
8'd120: post_data = 8'd189;
8'd121: post_data = 8'd189;
8'd122: post_data = 8'd190;
8'd123: post_data = 8'd190;
8'd124: post_data = 8'd191;
8'd125: post_data = 8'd192;
8'd126: post_data = 8'd192;
8'd127: post_data = 8'd193;
8'd128: post_data = 8'd194;
8'd129: post_data = 8'd194;
8'd130: post_data = 8'd195;
8'd131: post_data = 8'd195;
8'd132: post_data = 8'd196;
8'd133: post_data = 8'd197;
8'd134: post_data = 8'd197;
8'd135: post_data = 8'd198;
8'd136: post_data = 8'd198;
8'd137: post_data = 8'd199;
8'd138: post_data = 8'd199;
8'd139: post_data = 8'd200;
8'd140: post_data = 8'd201;
8'd141: post_data = 8'd201;
8'd142: post_data = 8'd202;
8'd143: post_data = 8'd202;
8'd144: post_data = 8'd203;
8'd145: post_data = 8'd203;
8'd146: post_data = 8'd204;
8'd147: post_data = 8'd205;
8'd148: post_data = 8'd205;
8'd149: post_data = 8'd206;
8'd150: post_data = 8'd206;
8'd151: post_data = 8'd207;
8'd152: post_data = 8'd207;
8'd153: post_data = 8'd208;
8'd154: post_data = 8'd208;
8'd155: post_data = 8'd209;
8'd156: post_data = 8'd209;
8'd157: post_data = 8'd210;
8'd158: post_data = 8'd211;
8'd159: post_data = 8'd211;
8'd160: post_data = 8'd212;
8'd161: post_data = 8'd212;
8'd162: post_data = 8'd213;
8'd163: post_data = 8'd213;
8'd164: post_data = 8'd214;
8'd165: post_data = 8'd214;
8'd166: post_data = 8'd215;
8'd167: post_data = 8'd215;
8'd168: post_data = 8'd216;
8'd169: post_data = 8'd216;
8'd170: post_data = 8'd217;
8'd171: post_data = 8'd217;
8'd172: post_data = 8'd218;
8'd173: post_data = 8'd218;
8'd174: post_data = 8'd219;
8'd175: post_data = 8'd219;
8'd176: post_data = 8'd220;
8'd177: post_data = 8'd220;
8'd178: post_data = 8'd221;
8'd179: post_data = 8'd221;
8'd180: post_data = 8'd222;
8'd181: post_data = 8'd222;
8'd182: post_data = 8'd223;
8'd183: post_data = 8'd223;
8'd184: post_data = 8'd224;
8'd185: post_data = 8'd224;
8'd186: post_data = 8'd225;
8'd187: post_data = 8'd225;
8'd188: post_data = 8'd226;
8'd189: post_data = 8'd226;
8'd190: post_data = 8'd227;
8'd191: post_data = 8'd227;
8'd192: post_data = 8'd228;
8'd193: post_data = 8'd228;
8'd194: post_data = 8'd229;
8'd195: post_data = 8'd229;
8'd196: post_data = 8'd230;
8'd197: post_data = 8'd230;
8'd198: post_data = 8'd230;
8'd199: post_data = 8'd231;
8'd200: post_data = 8'd231;
8'd201: post_data = 8'd232;
8'd202: post_data = 8'd232;
8'd203: post_data = 8'd233;
8'd204: post_data = 8'd233;
8'd205: post_data = 8'd234;
8'd206: post_data = 8'd234;
8'd207: post_data = 8'd235;
8'd208: post_data = 8'd235;
8'd209: post_data = 8'd235;
8'd210: post_data = 8'd236;
8'd211: post_data = 8'd236;
8'd212: post_data = 8'd237;
8'd213: post_data = 8'd237;
8'd214: post_data = 8'd238;
8'd215: post_data = 8'd238;
8'd216: post_data = 8'd239;
8'd217: post_data = 8'd239;
8'd218: post_data = 8'd240;
8'd219: post_data = 8'd240;
8'd220: post_data = 8'd240;
8'd221: post_data = 8'd241;
8'd222: post_data = 8'd241;
8'd223: post_data = 8'd242;
8'd224: post_data = 8'd242;
8'd225: post_data = 8'd243;
8'd226: post_data = 8'd243;
8'd227: post_data = 8'd243;
8'd228: post_data = 8'd244;
8'd229: post_data = 8'd244;
8'd230: post_data = 8'd245;
8'd231: post_data = 8'd245;
8'd232: post_data = 8'd246;
8'd233: post_data = 8'd246;
8'd234: post_data = 8'd246;
8'd235: post_data = 8'd247;
8'd236: post_data = 8'd247;
8'd237: post_data = 8'd248;
8'd238: post_data = 8'd248;
8'd239: post_data = 8'd248;
8'd240: post_data = 8'd249;
8'd241: post_data = 8'd249;
8'd242: post_data = 8'd250;
8'd243: post_data = 8'd250;
8'd244: post_data = 8'd251;
8'd245: post_data = 8'd251;
8'd246: post_data = 8'd251;
8'd247: post_data = 8'd252;
8'd248: post_data = 8'd252;
8'd249: post_data = 8'd253;
8'd250: post_data = 8'd253;
8'd251: post_data = 8'd253;
8'd252: post_data = 8'd254;
8'd253: post_data = 8'd254;
8'd254: post_data = 8'd255;
8'd255: post_data = 8'd255;
default: post_data = 8'd0;
endcase
end
endmodule
这里采用的是Y==0.4 的伽马曲线,想要什么曲线可以直接在MATLAB中调整即可,直接全自动无需写代码。