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
53 changes: 37 additions & 16 deletions lens_shading_analyse.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,27 +316,48 @@ int main(int argc, char *argv[])
uint16_t *channel = out_buf[channel_ordering[bayer_order][i]];
int mid_value_avg = 0;
int count = 0;
//Average out the centre 64 pixels.
for (x=(single_channel_width>>1)-4; x<=(single_channel_width>>1)+4; x++)
{
for (y=(single_channel_height>>1)-4; y<=(single_channel_height>>1)+4; y++)
{
mid_value_avg += channel[x + y*single_channel_width];
count++;
}
}
uint16_t middle_val = (mid_value_avg / count) << 5;

uint16_t *line;
const char *channel_comments[4] = {
"R",
"Gr",
"Gb",
"B"
};
printf("Middle_val is %d\n", middle_val);
};

// Search highest value
float max_val = 0;
for (y=0; y<grid_height; y++)
{
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++)
{
int x_start = x*32;
int x_stop = x_start + 32 <= single_channel_width ? x_start + 32 : single_channel_width;

float block_val = 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_val += line[x_px];
block_px++;
}
}

block_val /= block_px;
if(block_val > max_val){
max_val = block_val;
}
}
}

max_val *= 32;
printf("Max_val is %.0f\n", max_val);
Copy link
Owner

Choose a reason for hiding this comment

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

Without a better description I can't say for certain what this is meant to be doing, but it's very ugly to run the same loop twice, once to find this max_val, and then again to compute the cell gains.

Allocate arrays for block_val and block_px (if it's really necessary) and compute once. Calculating the gains then becomes an iteration over those arrays instead of the whole image.

(Sorry, embedded programming always makes you think of more efficient code).

Copy link
Author

Choose a reason for hiding this comment

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

Running the loop twice is of course not a high-performance solution. But it runs very fast on my Raspberry Pi 3B ;-)
Quick and dirty - I will fix it.

Copy link
Author

Choose a reason for hiding this comment

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

Double calculation loop removed

fprintf(header, "//%s - Ch %d\n", channel_comments[i], channel_ordering[bayer_order][i]);
uint16_t *line;

// Calculate gain for each block
for (y=0; y<grid_height; y++)
{
int y_start = y*32;
Expand All @@ -356,11 +377,11 @@ int main(int argc, char *argv[])
block_px++;
}
}
int gain = (middle_val*block_px) / block_sum;
int gain = (max_val*block_px) / block_sum + 0.5;
if (gain > 255)
gain = 255; //Clip as uint8_t
else if (gain < 32)
gain = 32; //Clip at x1.0
gain = 32; //Clip at x1.0, should never happen
fprintf(header, "%d, ", gain );
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.

uint8_t gain_bin = gain;
Expand Down