Automatic Gain Control in the RGB Domain

Table of Contents

Automatic Gain Control in the RGB Domain. 1

Table of Contents. 1

Introduction. 1

Traditional AGC.. 1

Adjustments for an RGB Domain. 2

Adjustments for the LHS Domain. 3

LHS Results. 4

The Algorithm.. 5

Test Traces. 7

AGC’ing a Section: RGB’s. 8

AGC’ing a Section: Example Outputs. 20

Index. 24

 

Introduction

The traditional method of automatic gain control (AGC) in the seismic domain is described Exploration Seismology: Volume 1 by R. E. Sheriff (Author), L. P. Geldart (Author). The algorithm is designed to increase contrast, minimize dynamic range, without distorting waveform on a seismic section. We describe that algorithm in the section “Traditional AGC.”

 

The algorithm will not work correctly in the RGB domain, for reasons explained in the section “Adjustments for an RGB Domain.” We find those adjustments, and then implement them in the section “The RGB/AGC Algorithm.” The code is implemented in the routine AGC of the SAFL library.

Traditional AGC

Given a series of samples from the interval  we want to scale the samples so that the average absolute value in a window is a constant, .

 

Let  be the samples in question. Without loss of generality we will assume  for all . Let

(1.1)

 

 

be the average. We call  the window of the AGC. We want to find the multiplicative factor  so that

(1.2)

 

 

has , a user provided number. This of course would mean that our AGC factor  is defined by , i.e.

(1.3)

.

 

Using (1.1) in (1.3), we get

(1.4)

.

 

F is called the AGC Factor.

 

In general, we have the  and we have a window of length N, which slides over the data. We recalculate  for each new value by sliding a left hand sample off the window, and adding a right hand element to the window.

 

It is also traditional to express the AGC as a factor, , the average gain. Thus, after AGC, we would have . In that case, equation (1.3) becomes

(1.5)

 

 

and equation (1.4) becomes

(1.6)

 

 

where  is the average of the absolute values of . (It is here that we relax our assumption that .)

 

Example: If all of the values of  are equal to , we would have , as expected. Then using (1.4) with  instead of , we get

(1.7)

,

 

that is our AGC factor is , and

(1.8)

.

 

In the case of a constant value, the AGC factor is just the new value over the old value, as you would expect.

 

Adjustments for an RGB Domain

We now consider the case of an RGB color channel. This means that the samples are from the interval [0,255].

 

We begin by normalizing the samples to the interval [-128,128] by subtracting 128 from each sample. Then we AGC the result, and add the 128 back in.

 

We want to apply an AGC, but we need the new version of the colors to remain in the interval [0,255], so the AGC cannot be too strong. We consider an example.

Suppose our samples are .After normalizing the data, we have:  and we want to AGC it.

We have

(2.1)

.

 

Using equation (1.5) for  and , we get

(2.2)

.

 

Thus, we will increase our values to 0 through 129. Some of the points will be outside the range of  [0,255]. If we had , our data would range to twice the starting interval, up to about 550.

 

AGC may extend a low amplitude window to beyond the range of [0,255]. For this reason, after we have completed our AGC, we will normalize the AGC output to the interval [-127,127] and then add 127 to get a final range of [0,254]. That output will maintain waveforms, i.e. contrast between layers, while equalizing the data across light and dark sections. Each AGC window will have the same average amplitude.

We run the AGC algorithm in the RGB channel in the program runAgc as follows:

     // We now AGC the Red, Blue, and Green

     uint nsamp = img.getRow();

     uint stride = img.getCol();

     double zero = 100;

     double outLier = 2.0;

     uint minSample = 0;

     uint maxSample = 255;

  for( i=0;i<img.getCol();i++)

          {

              agc( &(img.R[i]), nsamp, stride, window, percentage,

                         zero, outLier, minSample, maxSample );

              agc( &(img.G[i]), nsamp, stride, window, percentage,

                         zero, outLier, minSample, maxSample );

              agc( &(img.B[i]), nsamp, stride, window, percentage,

                         zero, outLier, minSample, maxSample );

          }

 

Notice that we have to AGC all three channels.

 

Adjustments for the LHS Domain

In the LHS domain, the parameters are in the interval . As a result, we apply the technique of the previous section to the interval [0,1] instead of the interval [0,255]. For this reason, the Algorithm section will only work with the arbitrary interval [S,T]. ]. We generalize the algorithm in the following section to handle both cases.

 

Thus, our call to the AGC routine, as used in the program runAgcI is:

     // We now AGC on the L Channel

     uint nsamp = img.getRow();

     uint stride = img.getCol();

     double zero = 0.5;

     double outLier = 0.05;

     uint minSample = 0;

     uint maxSample = 1;

     // Set up the I channel.

     img.RGB_HSI();

     for( i=0;i<img.getCol();i++)

          {

              // AGC the I channel.

              agc( &(img.I[i]), nsamp, stride, window, percentage,

                         zero, outLier, minSample, maxSample );

          }

 

LHS Results

Here are the results of using runAgcI on the data:

Here is a test slice before and after the agc:
Bright Agc on the I (intensity) channel, window 50 percentage 50:
Download the tif version.
Dark Agc on the I (intensity) channel, window 50 percentage 25:
Download the tif version.
Original
Download the tif version.
Rgb Agc
Download the tif version.
Mask of RgbAgc: We used the Rgb Agc to make a mask that could be used for correction if desired:
Download the tif version.
 
Here is a movie of the test plot with the various percentages, viewable on a PC. The movie will take about 30 seconds to load on a broadband connection.
To compare, here are a before and after movie of the first 20 slices. I note that the lateral variations are fixed, but there is still a hue shift around the tenth slice that needs fixing:
Before and After AGC of W 50, P 50 on the I channel.
For a list of all the files, go to here.

The method is documented here. There also is a PDF version of the document here.
The original data is at ppmList.

 

The Algorithm

We describe here the implementation of the RGB/AGC in the routine agc.cpp.

 

Suppose we want to AGC a set of samples . The steps are:

(1)   Mute the top and bottom. Since the pictures start and end with a white band, we start the AGC processing at the first non-T and non-S sample, and stop before the last contiguous non-T non-S section.

(2)   Subtract  from all samples.  will be the fixed point of the AGC, it should be your version of “gray.” Thus for some data, that point can be a different value. It need not be the midpoint of the possible range. You might want it to be the average point of the interesting range. Typically, , but not always.

(3)   After step (1), we have a set of data . Let N be the length of the window. Let A be our AGC factor, expressed as a percentage. Then we have

(4.1)

.

 

(4.2)

,

 

and

(4.3)

,

 

where

(4.4)

.

 

(Note that if  is the mid-point of , then .)

This will give an AGC centered on the interval .

We calculate by starting with a known , then take off the absolute value of the left-hand sample divided by N, then add the absolute value of the right hand sample divided by N. Thus we have a new  for each window. The  changes only gradually, preserving the wave shape, and the local contrast, while enhancing and equalizing the global contrast.

 

At the start of the data, we use a shortened window. That means the first point is unchanged, and the average of the first and second point is affected by the first through third points, and so on. At the end of the data, we reverse this process.

 

(4)   Once the series of new  are found, we renormalize if any of the new ones are outside . Call those new values . If  is the max of , we have:

(4.5)

.

 

 

(5)   Finally, we let

(4.6)

.

 

 

 

The resulting value is the RGB/AGC’ed value.

 

Here is a sample plot of the result:

The red line is the original, a damped sin wave. The green line is the AGC’ed result. The blue line is the factor used in the AGC. The latter starts around 1 and ends around 20, effectively removing the damping in the original sin wave.

 

Remember that this will only work if your AGC window contains several cycles of data. Otherwise, the AGC will mess up the frequencies and change the wave shapes.

 

Test Traces

It is necessary to apply the above to test traces taken from the sample data. We do that using getTraceRgb. Our sample traces are taken from the first section, 99_0_46. We take sample traces from these places:

AGC’ing a Section: RGB’s

The slice is 2986x1600, so the samples 1-6 are at

Sample Number

Percentage

Trace Number

1

4.50%

134

2

22.50%

672

3

41.40%

1236

4

79.50%

2374

5

85.50%

2553

6

91.00%

2717

Here are the plots of those samples. We show them in pairs, before and after the AGC.

The AGC parameters used were:

Parameter

Value

Zero

100

Window

12-200

outlier

2

minSample

0

maxSample

255

percentage

25-100

 

Choosing the parameters can be tricky. They definitely vary with the data case.

 

 

As you can see the characteristic cycle we want to AGC over is about 150 points. Thus a window of 200 points will AGC nicely. Also note that the most corrupted, i.e. whitened portions are also the portions where the red is lowest when compared to the blue, lending credence to the theory that the red is more sensitive to the dry spots. After AGC, the color channels are nicely merged.

 

This looks like a good set of parameters. We will apply them to the whole section.

 

AGC’ing a Section: Example Outputs

 

 

The results are dependent on the length of the window. A 200 point AGC window is about 1/3 of a section. A 50 point window is 1/12 of a section. There are about 25-30 “cycles” of events in a section, so a window down to 25 is possible. Here are several outputs, with varying window sizes:

Window = 12 Percentage = 70

Window = 25 Percentage = 70

Window = 50 Percentage = 70

Window = 100 Percentage = 70

Original

 

As you can see, as the window size decreases, the contrast across the section also decreases. We can fix this to some extent, my increasing the “percentage” parameter which is currently at 70. (The percentage means the percentage of 255 that we want the samples to range over. For the case of 70 it is around 80. Raising the percentage to 100 would increase the range to about 100.) To give you a feel for that, here is the results of the 25 and 50 window with a percentage of 100:

Window = 25 Percentage = 100

Window = 25 Percentage = 100

 

If you do fiddle with the percentage, you will also want to fiddle with the “zero” to prevent overlapping of corrections, i.e. too high of a percentage will result in too much clipping, and loss of dynamic range at the very black and white.

 

As another option, we can reduce the percentage, and hopefully experience less clipping:

 

Window = 50 Percentage = 50

 

 

The PPM files are listed in ./ppmList.html. You can download them and look at them on a monitor.

 

 

 

 

 

Keep in mind that with any window size, applying AGC to all sections will equalize the average amplitude in each section.

 

We have not optimized the code yet, but it still runs a section in 12 seconds on a 1.4Ghertz AMD PC.

 

Overall, the results are promising; we just need to find the right parameters. Remember that if we AGC all sections, all inter-section contrasts will disappear, and that will be a good thing.

 

Index


AGC........................... 1, 2, 3, 4, 5, 6, 7, 8, 20, 23, 24

agc.cpp..................................................................... 5

AMD...................................................................... 23

amplitude............................................................ 3, 23

black....................................................................... 23

channel........................................................ 2, 3, 4, 20

clipping................................................................... 23

frequencies................................................................ 7

getTraceRgb............................................................. 7

intensity..................................................................... 4

max........................................................................... 6

maxSample....................................................... 3, 4, 9

minSample........................................................ 3, 4, 8

percentage........................................ 8, 20, 21, 22, 23

Red....................................................................... 1, 3

RGB................................................. 1, 2, 3, 4, 5, 6, 8

RGB/AGC........................................................ 1, 5, 6

runAgc...................................................................... 3

runAgcI..................................................................... 4

Saint Anthony Falls Laboratory.................................. 1

seismic...................................................................... 1

Sheriff....................................................................... 1

trace................................................................. 1, 7, 8

wave..................................................................... 6, 7

waveform.............................................................. 1, 3

white............................................................. 6, 20, 23

window............................... 1, 2, 3, 4, 6, 7, 20, 22, 23

windows........................................... 8, 20, 21, 22, 23

zero............................................................ 3, 4, 8, 23