Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Several small improvements #3

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
45 changes: 21 additions & 24 deletions lens_shading_analyse.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,35 +310,32 @@ int main(int argc, char *argv[])

fprintf(header, "//%s - Ch %d\n", channel_comments[i], channel_ordering[bayer_order][i]);
uint16_t *line;
for (y=16; y<single_channel_height+32; y+=32) //Grid size is 64x64, but the component tables are subsampled due to the Bayer pattern
for (y=0; y<grid_height; y++)
{
if (y>=single_channel_height)
line = &channel[(single_channel_height-1)*(single_channel_width)];
else
line = &channel[y*(single_channel_width)];

for(x=16; x<single_channel_width; x+=32)
int y_start = y*32;
int y_stop = y_start + 32 <= single_channel_height ? y_start + 32 : single_channel_height;
for (x=0; x<grid_width; x++)
{
//Average 3 pixels horizontally to give some noise rejection
int avg = line[x] + line[x-1] + line[x+1];
int gain = (middle_val*3) / avg;
int x_start = x*32;
int x_stop = x_start + 32 <= single_channel_width ? x_start + 32 : single_channel_width;

uint32_t block_sum = 0;
uint16_t block_px = 0;

for(int y_px = y_start; y_px < y_stop; y_px++){
line = &channel[y_px*(single_channel_width)];
for(int x_px = x_start; x_px < x_stop; x_px++){
block_sum += line[x_px];
block_px++;
}
}
int gain = (middle_val*block_px) / block_sum;
if (gain > 255)
gain = 255; //Clip as uint8_t
gain = 255; //Clip as uint8_t
else if (gain < 32)
gain = 32; //Clip at x1.0
gain = 32; //Clip at x1.0
fprintf(header, "%d, ", gain );
fprintf(table, "%d %d %d %d\n", x, y, gain, i );
}
//Compute edge value from the very edge 2 pixels.
{
int avg = line[single_channel_width-2] + line[single_channel_width-1];
int gain = (middle_val*2) / avg;
if (gain > 255)
gain = 255; //Clip as uint8_t
else if (gain < 32)
gain = 32; //Clip at x1.0
fprintf(header, "%d,\n", gain );
fprintf(table, "%d %d %d %d\n", x, y, gain, i );
fprintf(table, "%d %d %d %d\n", x * 32 + 16, y * 32 + 16, gain, i );
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels wrong.
The ISP interpolates the values at the centre of each grid cell, and interpolates between them. This is averaging over the entire cell, therefore is just a smoothing filter.

Enlarging the average to 5x5, or even up as far as 9x9 would be reasonable, but otherwise you're ignoring a large amount of the detail.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know which algorithm is used for the interpolation. I don't see a problem with this approach. From my point of view and for my applications the results are better.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been thinking again. If you look at lens shading across the width (alternatively across the height), the brightness will be a function similar to figure a. The average value changes only slightly with the width of the viewed area. However, the brightness signal from the sensor is subject to noise (figure b). A wider area improves the average value. Only in case of peaks smaller areas are better (figure c). In this case, however, the peak would have to lie exactly in a calculation area.

lens_shading

Or am I misunderstanding something?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integrated a parameter for the cell size.

}
}

Expand Down