Gamma校正算法
30个输入定点值计算(C++)
for(i=1; i<=gammaPointSize; i++) { if(gammaTableIn[i-1] < 1023) { if(i == 1) { gammaTableIn[i] = gammaTableIn[i-1] + stepLevelFirst-1; } else { gammaTableIn[i] = gammaTableIn[i-1] + stepLevelFirst; } } else if(gammaTableIn[i-1] < 2047) { gammaTableIn[i] = gammaTableIn[i-1] + stepLevelSecond; } else if(gammaTableIn[i-1] < 3071) { gammaTableIn[i] = gammaTableIn[i-1] + stepLevelThird; } else { gammaTableIn[i] = gammaTableIn[i-1] + stepLevelFourth; } }
30个定点值中间使用线性插值(C++)
//以R作为示例 for(row=0; row<height; row++) { for(col=0; col<width; col++){ pixelValR = imgInR[row*width+col]; pixelValG = imgInG[row*width+col]; pixelValB = imgInB[row*width+col]; } if(gamma_para.GAMMA_EN == 0){ imgOutR[row*width+col] = pixelValR>>4; imgOutG[row*width+col] = pixelValG>>4; imgOutB[row*width+col] = pixelValB>>4; } else{ if(pixelValR < gammaTableIn[16]){ startIndex = pixelValR / 64; endIndex = startIndex + 1; imgOutR[row*width+col] = (pixelValR - gammaTableIn[startIndex])*(gamma_para.GAMMA_TABLE_OUT[endIndex] - gamma_para.GAMMA_TABLE_OUT[startIndex])/64 + gamma_para.GAMMA_TABLE_OUT[startIndex]; } else if(pixelValR < gammaTableIn[24]){ startIndex = 16 + (pixelValR-gammaTableIn[16]) / 128; endIndex = startIndex + 1; imgOutR[row*width+col] = (pixelValR - gammaTableIn[startIndex])*(gamma_para.GAMMA_TABLE_OUT[endIndex] - gamma_para.GAMMA_TABLE_OUT[startIndex])/128 + gamma_para.GAMMA_TABLE_OUT[startIndex]; } else if(pixelValR < gammaTableIn[28]){ startIndex = 24 + (pixelValR-gammaTableIn[24]) / 256; endIndex = startIndex + 1; imgOutR[row*width+col] = (pixelValR - gammaTableIn[startIndex])*(gamma_para.GAMMA_TABLE_OUT[endIndex] - gamma_para.GAMMA_TABLE_OUT[startIndex])/256 + gamma_para.GAMMA_TABLE_OUT[startIndex]; } else{ startIndex = 28 + (pixelValR-gammaTableIn[28]) / 512; endIndex = startIndex + 1; imgOutR[row*width+col] = (pixelValR - gammaTableIn[startIndex])*(gamma_para.GAMMA_TABLE_OUT[endIndex] - gamma_para.GAMMA_TABLE_OUT[startIndex])/512 + gamma_para.GAMMA_TABLE_OUT[startIndex]; } if(imgOutR[row*width+col]<128) imgOutR[row*width+col] = imgOutR[row*width+col] + gamma_para.DC - (gamma_para.DC*imgOutR[row*width+col]>>7); } }
Verilog实现(R像素举例)
/*** ----------R_index-----------***/ always @(posedge clk or negedge rst_n) begin if(!rst_n)begin startIndexR <= 12'b0; endIndexR1 <= 12'b0; startIndexR1 <= 12'b0; stater <= state1; end else begin if(!GAMMA_EN)begin imgOutR <= imgInR>>4; end else begin imgInR1 <= imgInR; imgInR2 <= imgInR1; if(imgInR<gammaTableIn[16])begin startIndexR <= imgInR >> 6; startIndexR1 <= startIndexR ; endIndexR1 <= startIndexR+1; stater <= state1; end else if(imgInR<gammaTableIn[24])begin startIndexR <= ((imgInR-gammaTableIn[16])>>7) +16; startIndexR1 <= startIndexR ; endIndexR1 <= startIndexR+1; stater <= state2; end else if(imgInR<gammaTableIn[28])begin startIndexR <= ((imgInR-gammaTableIn[24])>>8) +24; startIndexR1 <= startIndexR ; endIndexR1 <= startIndexR+1; stater <= state3; end else begin startIndexR <= ((imgInR-gammaTableIn[28])>>9) +28; startIndexR1 <= startIndexR ; endIndexR1 <= startIndexR+1; stater <= state4; end end end end //----------------Rcaculation---------------// always @(posedge clk or negedge rst_n) begin if(!rst_n)begin imgOutR <= 0; end else if(GAMMA_EN)begin case(stater) state1:begin imgOutR <= ((imgInR2 - gammaTableIn[startIndexR1])*((GAMMA_TABLE_OUT[endIndexR1] - GAMMA_TABLE_OUT[startIndexR1])>>6) + GAMMA_TABLE_OUT[startIndexR1])>>4; end state2:begin imgOutR <= ((imgInR2 - gammaTableIn[startIndexR1])*((GAMMA_TABLE_OUT[endIndexR1] - GAMMA_TABLE_OUT[startIndexR1])>>7) + GAMMA_TABLE_OUT[startIndexR1])>>4; end state3:begin imgOutR <= ((imgInR2 - gammaTableIn[startIndexR1])*((GAMMA_TABLE_OUT[endIndexR1] - GAMMA_TABLE_OUT[startIndexR1])>>8) + GAMMA_TABLE_OUT[startIndexR1])>>4; end state4:begin imgOutR <= ((imgInR2 - gammaTableIn[startIndexR1])*((GAMMA_TABLE_OUT[endIndexR1] - GAMMA_TABLE_OUT[startIndexR1])>>9) + GAMMA_TABLE_OUT[startIndexR1])>>4; end endcase end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rout <=0; end else begin if(GAMMA_EN)begin if((imgOutR)<12'd128)begin rout <= imgOutR + DC - (DC*imgOutR>>7); end rout <= imgOutR; end end end
Testbench仿真及激励
`timescale 1ns/1ps module GAMMA_TABLE_OUT(); parameter period = 10; reg clk =0; reg rst_n =0; reg GAMMA_EN; reg [11:0] imgInR; reg [11:0] imgInG; reg [11:0] imgInB; wire[7:0] imgOutR; wire[7:0] imgOutG; wire[7:0] imgOutB; initial begin forever#(period/2) clk = ~clk; end initial begin forever#(period*10) rst_n = 1; end initial begin #2; rst_n = 0; imgInB = 0; imgInG =0; imgInR =0; GAMMA_EN =0; #(period*20) rst_n = 1; GAMMA_EN =1; repeat(10)begin #(period*500) img_data(); end #(period*20); $stop; end task img_data; integer i; begin #(period*100); for(i=0;i<1228800;i=i+1)begin #(period); imgInR = $random%4096(); imgInG = $random%4096(); imgInB = $random%4096(); end end endtask gamma inst_gamma( .clk (clk), .rst_n (rst_n), .imgInR (imgInR), .imgInG (imgInG), .imgInB (imgInB), .imgOutR (imgoutR), .imgOutG (imgoutG), .imgOutB (imgoutB), .GAMMA_EN (GAMMA_EN) ); endmodule
=0.4时outTable参考查找表
GAMMA_TABLE_OUT[0] <= 12'd0; GAMMA_TABLE_OUT[1] <= 12'd771; GAMMA_TABLE_OUT[2] <= 12'd1021; GAMMA_TABLE_OUT[3] <= 12'd1202; GAMMA_TABLE_OUT[4] <= 12'd1349; GAMMA_TABLE_OUT[5] <= 12'd1475; GAMMA_TABLE_OUT[6] <= 12'd1587; GAMMA_TABLE_OUT[7] <= 12'd1688; GAMMA_TABLE_OUT[8] <= 12'd1781; GAMMA_TABLE_OUT[9] <= 12'd1867; GAMMA_TABLE_OUT[10] <= 12'd1948; GAMMA_TABLE_OUT[11] <= 12'd2024; GAMMA_TABLE_OUT[12] <= 12'd2095; GAMMA_TABLE_OUT[13] <= 12'd2164; GAMMA_TABLE_OUT[14] <= 12'd2229; GAMMA_TABLE_OUT[15] <= 12'd2291; GAMMA_TABLE_OUT[16] <= 12'd2351; GAMMA_TABLE_OUT[17] <= 12'd2465; GAMMA_TABLE_OUT[18] <= 12'd2571; GAMMA_TABLE_OUT[19] <= 12'd2671; GAMMA_TABLE_OUT[20] <= 12'd2766; GAMMA_TABLE_OUT[21] <= 12'd2856; GAMMA_TABLE_OUT[22] <= 12'd2942; GAMMA_TABLE_OUT[23] <= 12'd3024; GAMMA_TABLE_OUT[24] <= 12'd3103; GAMMA_TABLE_OUT[25] <= 12'd3253; GAMMA_TABLE_OUT[26] <= 12'd3393; GAMMA_TABLE_OUT[27] <= 12'd3525; GAMMA_TABLE_OUT[28] <= 12'd3650; GAMMA_TABLE_OUT[29] <= 12'd3882; GAMMA_TABLE_OUT[30] <= 12'd4095;
Gamma Correction函数参考图