cpixip
Posts: 25
Joined: Mon May 01, 2017 7:56 am

Re: Custom lens shading tables

Sun Nov 19, 2017 7:30 pm

Fer wrote:
Sun Nov 19, 2017 3:00 pm
... I use the Camera Board with an enlarger lens...

- funny: the Schneider Componon-S 2.8/50 I am using is originally an enlarger lens...

The project I want to use this lens for is a high-quality Super 8 film scanner, based mostly on the raspi-hardware. For a film scanner you have to capture and process thousands of images in a reasonable time. And the frames of a Super 8 movie are tiny!

I tested the feasibility of various image sensors, from DSLR over high end video cameras to the raspi cameras. The raspi cameras offered reasonable image quality, an easy way to save and transfer captured frames and the possibility to control the mechanics as well as the illumination system from the Pi. So I chose the Pi camera as the primary option for the scanner.

However, I soon encountered some basic issues with the raspi cameras:
  1. the lens shading is hardwired, so changing the lens is everything from difficult to impossible.
  2. the camera slows down if exposure times get longer. Changing any setting takes only effect after at least one frame.
  3. all of the "auto" functions get into your way of using the pi camera. There are ways to defeat them, but it is cumbersome. For example, after requesting a certain exposure time, it takes one to three frames until the camera even reports that it has obtained the requested exposure. Which is even not correct at that point in time. It takes further one to three frames until the data really refelcts the requested exposure. So in the end, you have to wait sometimes (this varies) up to six frames before you get the exposure time you requested....
  4. I did try the c-software available, but its involved... (I am a long time c-programmer). The fastest way (both in getting results and streaming images) I could figure out was to get the data out of the camera by using picamera's "capture_sequence" command together with "use_video_port=True" in a client-server scheme. 40 fps @ 800x600 pixels is no problem.
Well, after these initial findings, I tried to get rid of the lens shading (this was at a time when the v1-cam was "fresh" and the v2-cam not yet available).

I tried the following:
  1. reading the raw image from the sensor and post-processing this with own software, including lens shading compensation. Did work, but was way too slow. Post-processing on the raspi at that time was not feasible anyway and just sending the huge raw image via LAN to a PC turned out to be the major bottleneck. In summary: not fast enough, even today.
  2. sending for each captured frame several jpgs with different exposure times over the LAN-line, creating out of these frame a HDR image of the captured frame.

    The reason for this: creating a HDR out of a set of jpegs (LDRs) basically undos much of the processing done in the raspi-image pipeline. Since a HDR encodes scaled radiance values, it just as good as the raw image, but without the hassle of de-mosaicing and so on. Actually, if you do it right, it features a much improved signal-to-noise ratio, compared to a raw image. Anyway - once you have a HDR, the lens shading compensation is a simple matter of dividing the HDR by a previously captured HDR-frame with the camera just looking at a homogeneous white background.

    Again, such an approach would not work with a simpe jpg as the pixel values do not linearly depend on radiance values.

    Well, this approach worked, but it turned out that it is not so easy to convert a HDR back into a LDR image. At least not a LDR image which you can use for video creation. The results were sometimes great, sometimes bad, depending on the visual content of the frame.
  3. so my current approach still captures 3-5 images with different exposures, but I combine them via a derivative of the enfuse-algorithm. The enfuse algorithm creates images similar in appearance to a well-mapped HDR, but avoids calculating an intermediate HDR. This enfuse-approach gives me consistently visually pleasing results, very close to the original film look.

    The only problem left is again the lens shading compensation. I tried two approaches:
    1. keeping the original lens but modifying the optics in such a way that I get a sufficiently large image of the Super 8 frame. That means either that I unscrew the original lens as much as possible to change focus (that did not give me a sufficient magnification) or that I use some magnifier in front of the standard lens (I could not find any magnifier which showed decent performance)
    2. use a good lens (for example the Schneider Componon-S 2.8/50) and get the lens shading working (this is what this thread is about)
... so, that was a long story, but it might help others to read this.

Coming back to the issue of getting rid of the lens shading in post processing: I think you will have to go from computations done with LDRs (jpg or whatever) to computations with HDRs, as these are the only image formats (except raw images) which correctly code in linear radiance space, and than transfer the HDR back to something usable for display. When acquiring LDRs for the creation of a HDR, be sure to wait at least 6 frames before taking the actual capture. Otherwise, the exposure which is record in the EXIF-data might not be the exposure the camera actually used.

Of course, the best option (at least in terms of processing time) is still a working lens shading compensation.... - so let's see what can be done here!

Fer
Posts: 35
Joined: Tue Feb 21, 2017 10:27 am

Re: Custom lens shading tables

Mon Nov 20, 2017 11:55 am

The project I want to use this lens for is a high-quality Super 8 film scanner, based mostly on the raspi-hardware
Me too! That's exactly my project.
I've been working on it since a year or so.
I can now take JPEG stills very fast with a RPI3 by using a modified version of Raspivid.
At the moment, my only serious issue is with the embedded lens shading correction. My lens does not need a correction, so the embedded shading and sharpness correction is degrading the images, instead.
This, and the pain in trying to remain aligned with the various versions of Raspivid (diff + patch not always works).
I'm using a V1 C-Mount camera module by the way.

cpixip
Posts: 25
Joined: Mon May 01, 2017 7:56 am

Re: Custom lens shading tables

Sat Nov 25, 2017 4:24 pm

Fer wrote:
Mon Nov 20, 2017 11:55 am
At the moment, my only serious issue is with the embedded lens shading correction. My lens does not need a correction, so the embedded shading and sharpness correction is degrading the images, instead.
There is the possibility to switch off the lens shading correction completely. The lens shading version of raspistill does this if you capture a raw image.

However, there are micro-lenses on the sensor chip of the Raspberry Pi camera, and they are tuned to the focal length of the original lens. If you put another lens with a different focal length in front of the sensor, you will need lens shading correction even if your lens would be an ideal lens.

The Componon-S I am using is a very good enlarger lens, facilitating sensor sizes several times larger than the Pi's camera. It works very good with plain sensors, without micro lenses. Using the Pi's sensors with its micro lenses, you get a horrible color signal out - even with the lens shading turned off. To counter that, one is indeed required to perform a lens shading correction.

Actually, the effect is much more pronounced with the v2-cameras than the v1-cams. An example where you can compare the two sensors can be found here: viewtopic.php?f=43&t=196297

From my experience, sharpness can be tuned over a wide range - is that really affecting your results negatively?

Fer
Posts: 35
Joined: Tue Feb 21, 2017 10:27 am

Re: Custom lens shading tables

Sat Nov 25, 2017 5:06 pm

Well, I'm using an even better :-) enlarger lens (Apo-Rodagon; I also have your Componon-S by the way), plus various special purpose Computar industrial inspection lenses.
Indeed they have some issues with microlenses: those were probably tuned to compensate for oblique ray angles, because of the very short backfocal distance of the Raspberry camera module; probably something like Leica M9 radial-shift microlenses arrangement.
It's even worse with V2 probably because of higher pixels (and microlenses) density; plus, they ship V2 with a shorter (wider) lens, which probably needed even stronger-correcting microlenses design.
Our lenses would work much better with "straight" microlenses, but such is life. :(
It would be GREAT for me if someone could produce legally-licensed alternative camera modules, with straight microlenses (and a proper lens mount as well). I'm confident there's a nice market for that, even at 3x the price of stock camera module. I personally know a lot of projects based upon Raspberry camera modules, which had to be hacked to purpose.

Now about lens shading on Raspistill... I was not able to switch off shading correction and sharpness correction in Raspistill 1.3.11 (yes I tried the special edition with ability to exclude correction), despite having followed 6x9's directions.
Now my custom code is so far from raspistill, I can't patch it anymore.
And yes, raspistill's built-in sharpness correction (which I can't switch off as well) indeed damages my images, because it applies a somewhat large-radius radial sharpening, again to correct poor border sharpness of the stock lens.
At the moment, I'm applying a reverse-correction after the capture, which obviously is far from ideal, but at least it suits my purpose at this stage.

I hope one day plain-vanilla/stock/mainline Raspistill will easily (or even not-so-easily) allow for custom lens-shading correction, custom lens-sharpness correction, and the option to turn them off completely. Then I will resync my code again. As for now, it's too difficult for me keeping track of the various Raspistill versions out there (special versions etc.).

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 20477
Joined: Sat Jul 30, 2011 7:41 pm

Re: Custom lens shading tables

Sat Nov 25, 2017 5:16 pm

cpixip wrote:
Sat Nov 25, 2017 4:24 pm
There is the possibility to switch off the lens shading correction completely. The lens shading version of raspistill does this if you capture a raw image.

However, there are micro-lenses on the sensor chip of the Raspberry Pi camera, and they are tuned to the focal length of the original lens. If you put another lens with a different focal length in front of the sensor, you will need lens shading correction even if your lens would be an ideal lens.
raspistill when outputting raw doesn't switch off lens shading, but extracts the raw data prior to any processing (i.e. lens shading). The standard image still goes through the ISP and therefor has lens shading correction added.

The microlenses on the sensor are NOT tuned to a particular lens. As far as we know, they are all the same whatever the lens used. Otherwise, the sensor would need to be tuned on the production line to whatever lens is going to be attached, and that simply doesn't happen. We also think that all the microlenses are the same on the sensor die, ie, they don't change depending where they are on the die. Again, since during production of the sensor, the lens being used is unknown, it's not something that is useful. If anyone has any information (from sensor makers) that says something else, I would be interested to see it.

I'm not sure where this mis-information originated tbh.
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Please direct all questions to the forum, I do not do support via PM.

Fer
Posts: 35
Joined: Tue Feb 21, 2017 10:27 am

Re: Custom lens shading tables

Sat Nov 25, 2017 6:37 pm

Actually, it would make perfect sense to have a camera module such as the OV5647 tuned for certain kind of lenses, because those sort of sensors are mostly used on (cheaper) cellphones, and nearly all cheap cellphones use very similar lenses, focal-length-wise (from 26 to 35mm in 24x36-equivalent terms).
But some of us see the potential lying in the RPI platform for scientific research, wildlife preservation, robotics, special purpose etc.
Thus the need for "special stuff".
Of course everyone understands the choice of a very cheap camera module, given the main goal of Raspberry Foundation. It's just that it would be great to have (officially supported/licensed) better alternatives, even if (obviously) pricier.

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5664
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Custom lens shading tables

Sat Nov 25, 2017 9:11 pm

jamesh wrote:
Sat Nov 25, 2017 5:16 pm
cpixip wrote:
Sat Nov 25, 2017 4:24 pm
There is the possibility to switch off the lens shading correction completely. The lens shading version of raspistill does this if you capture a raw image.

However, there are micro-lenses on the sensor chip of the Raspberry Pi camera, and they are tuned to the focal length of the original lens. If you put another lens with a different focal length in front of the sensor, you will need lens shading correction even if your lens would be an ideal lens.
raspistill when outputting raw doesn't switch off lens shading, but extracts the raw data prior to any processing (i.e. lens shading). The standard image still goes through the ISP and therefor has lens shading correction added.
My hacked version for doing the lens shading calibration does disable lens shading when capturing raws so that it shows up how significant the artifacts from the lens are. That version is not meant to be a mainstream version though.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
Please don't send PMs asking for support - use the forum.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

Fer
Posts: 35
Joined: Tue Feb 21, 2017 10:27 am

Re: Custom lens shading tables

Sat Nov 25, 2017 10:19 pm

So I need to use this special version of Raspistill to build a custom lens shading correction header, ok.
But then, should I compile this custom header into current mainstream Raspistill (https://github.com/raspberrypi/userland ... spiStill.c), or is a (different) special version needed?
Thanks

cpixip
Posts: 25
Joined: Mon May 01, 2017 7:56 am

Re: Custom lens shading tables

Sat Nov 25, 2017 10:58 pm

jamesh wrote:
Sat Nov 25, 2017 5:16 pm

raspistill when outputting raw doesn't switch off lens shading, but extracts the raw data prior to any processing (i.e. lens shading). The standard image still goes through the ISP and therefor has lens shading correction added.

Sorry for being not precise enough - I was referring to 6x9 hacked, special raspistill version which he mentioned at the thread start.
jamesh wrote:
Sat Nov 25, 2017 5:16 pm
The microlenses on the sensor are NOT tuned to a particular lens. As far as we know, they are all the same whatever the lens used. Otherwise, the sensor would need to be tuned on the production line to whatever lens is going to be attached, and that simply doesn't happen. We also think that all the microlenses are the same on the sensor die, ie, they don't change depending where they are on the die. Again, since during production of the sensor, the lens being used is unknown, it's not something that is useful. If anyone has any information (from sensor makers) that says something else, I would be interested to see it.

Well, again sorry for being not precise. I wrote above "tuned to the focal length..." .

That is true, to a certain extend. Micro lenses serve two purposes: first, they are used to direct more light energy towards the sensitive part of each pixel. Each pixel has a fill factor less than 100%, because there is wiring and transistors not sensitive to the incoming light within the area of each pixel.

If you place a tiny lens in front of each pixel, you can direct more light coming from the aperture of the lens onto the sensitive area of each pixel. The fill factor increases, and the sensor gets more sensitive.

The second thing micro lenses are used for is to compensate the chief ray angle (CRA). This is basically the angle the incoming light is hitting the sensor. Obviously, it varies from the center to the edge of the sensor. You can compensate for this by shifting each micro lens by a tiny amount, so it is looking "better" toward the aperture of the lens. Clearly, the chief ray angle will be different for lenses with small or large focal lengths, as the imaging geometries are different. A lens with a very large focal length does practically have no CRA variation over the sensor, a lens with a very small focal length does have a noticeable variation.

Technically, one way to achieve a certain CRA compensation for a given imaging geometry is to use a slightly different pitch for the micro lens array with respect to the pitch of the pixel array.

Clearly, the CRA compensation is "backed into" the sensor in question during production; it is varying in a certain way from center to egde of the sensor and is most of the time available from some datasheet.

By design, there is an optimal lens corresponding to the specific micro lens array which was put onto the bare sensor chip during production. Other lenses with comparable parameters will work nearly as good as the one the micro lens array was designed for (hint: the lens shading compensation can take care of this) , but if you use lenses with hugely different properties, you might run into difficulties (hint: the lens shading compensation might not work to satisfaction).

One of my goals is to find out the limits of what you can do with a standard Pi sensor chip mated with a different lens. That is why 6x9's lens shading algorithm is so important.

cpixip
Posts: 25
Joined: Mon May 01, 2017 7:56 am

Re: Custom lens shading tables

Sat Nov 25, 2017 11:05 pm

Fer wrote:
Sat Nov 25, 2017 10:19 pm
So I need to use this special version of Raspistill to build a custom lens shading correction header, ok.
But then, should I compile this custom header into current mainstream Raspistill (https://github.com/raspberrypi/userland ... spiStill.c), or is a (different) special version needed?
Thanks
You need to use the special version in order to load the ls_table.h into the image pipeline. The current mainstream version will not work. Also, be sure to checkout the appropriate branch (somewhere above there is a listing with the appropriate commands).

How the ls_table.h can be loaded into the image pipeline is described in detail in a comment at the top of the lens_shading_analyse.c program of 6x9. About 20 lines of code. Also, the same code section can be found in the special raspistill-version of 6x9's repo.

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 20477
Joined: Sat Jul 30, 2011 7:41 pm

Re: Custom lens shading tables

Sun Nov 26, 2017 9:49 am

cpixip wrote:
Sat Nov 25, 2017 10:58 pm
By design, there is an optimal lens corresponding to the specific micro lens array which was put onto the bare sensor chip during production. Other lenses with comparable parameters will work nearly as good as the one the micro lens array was designed for (hint: the lens shading compensation can take care of this) , but if you use lenses with hugely different properties, you might run into difficulties (hint: the lens shading compensation might not work to satisfaction).
You are mostly correct, but remember that the sensor array and the complete sensor module are not necessarily made by the same manufacturer on the same production line. So when the array and microlens assembly is manufactured, there is often no real knowledge of what lens module it will be used with, or even the packaging that is will be assembled in.

I'm trying to remember if the Sony sensor is all in house, or whether the packaging is done externally, my recollection is that they make the sensor, but the module with lens assembly is made elsewhere. Certainly, it would be different departments at Sony if all 'in house'. Hence the information on the sensor itself not mentioning anything to do with lens type (https://www.sony-semicon.co.jp/products ... 219_e.html).

The OMX sensor (V1) we supplied is certainly made from parts (sensor, lens module) from different manufacturers. We just bought in a completed module, the omnivision sensor itself, packaged by Sunny IIRC.
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Please direct all questions to the forum, I do not do support via PM.

Fer
Posts: 35
Joined: Tue Feb 21, 2017 10:27 am

Re: Custom lens shading tables

Sun Nov 26, 2017 11:18 am

the sensor array and the complete sensor module are not necessarily made by the same manufacturer on the same production line
This is not much important.
The point being, those kind of sensors (1/4", 1/3.2") are designed for a certain target market, which is basically the lower tier of smartphones.
Camera modules for smartphones are universally designed to be as slim as possible, which implies very short backfocal distance and shorty focal lenses. All manufacturers follow this rule for this market segment.
This translates in steep chief ray angles. To obtain a decent image quality in this scenario, offset microlenses are more or less a given, so it's quite possible that whatever the manifacturer, whatever the mix from different sources, a microlenses array for a 1/4" sensor is offset type. This is not even mentioned in many official datasheets (hey, not even the spectral response is documented, which is much more important).
Result: the stock Raspberry Camera Module works great, expecially for the price.

Now, fast forward to the situation at hand. Some users including myself are employing large, telecentric lens designs. Long backfocal distance, long focal length, moderate chief ray angle. Quite the opposite vs. sensor design scenario.
Of course the correction built into the sensor (microlenses arrangement + lens shading/sharpness correction) works against us: thus we have this ugly green center / magenta border cast, reverse vignetting, uneven sharpness etc.

And since even totally disabling Raspistill correction we still see non-uniform frames (from lenses documented+tested to be totally uniform on 1/4" cover circle), the culprit has to be the microlenses array.

cpixip
Posts: 25
Joined: Mon May 01, 2017 7:56 am

Re: Custom lens shading tables

Sun Nov 26, 2017 9:28 pm

ok. Returning to the lens shading compensation, I did the following experiment:
  1. Captured a raw reference frame of a gray card:

    Code: Select all

    raspistill -r -o reference_raw.jpg
    
  2. Created a ls_table.h compensation table.

    Code: Select all

    cd ~/lens_shading/
    ./lens_shading_analyse reference_raw.jpg 
    cp ls_table.h ~/userland/host_applications/linux/apps/raspicam/
    cd ~/userland/
    ./buildme
    cd ..
    
  3. Captured again an image of the gray card, this time with lens shading compensation enabled:

    Code: Select all

    raspistill -o compensated.jpg
    

Here's a small analysis of the "compensated.jpg"-frame captured (resolution reduced for the analysis to 800x600 pixel).

Ideally, we should just see a uniform gray plane... :
Result_Lens_Shading_Compensation.JPG
Result_Lens_Shading_Compensation.JPG (68.35 KiB) Viewed 1736 times
Some things can be derived from the image analysis:
  • There are some very bright image patches close to the center of the image. These patches can be traced back to scaler entries = 31<32 in the ls_table.h. Most probably caused by a slightly off scaling during the computation of the ls_table.h.
  • Overall, some color noise with a low spatial frequency is visible. This is caused by the lens_shading_analyse examining not sufficiently many pixel values for the computation of the compensation of each patch. Was discussed before.
  • The values along the red line in the image are displayed in the upper plot. As one can see, the RGB-lines are not straight. In fact, they show a nearly symmetric deviation around the center of the image.
  • There is a tiny dark yellow line visible right at the bottom of the image. One can see this also as a drop of the blue line around the 600 pixel coordinate in the upper plot as well.
Whereas the first two points are easily to correct (in fact, they do not show up in the same experiment with the python implementation), the two other are more interesting. As far as I understand the Pi image pipeline, the ls_table.h matrix is zoomed up to the resolution of the raw image, and than used as a multiplier for each pixel. Assuming the ls_table.h was correctly calculated, there might be something wrong in the image pipeline implementation.

So I checked the accuracy of the ls_table. I took the ls_table.h calculated by the lens_shading_analyse program, scaled it up to raw image resolution and multiplied the raw reference image with the resulting scaling matrix. The result was perfect (safe of the color noise):
ls_table_applied_to_raw.JPG
ls_table_applied_to_raw.JPG (79.92 KiB) Viewed 1736 times
...so... - I think that this is a strong indication that the implementation in the image pipeline is not as perfect as it could be. As I do not have access to this implementation, I can only speculate. One reason we do not get straight lines in the image pipeline processing might be that the upscaling of the ls_table.h is slightly off. That would result in a small spatial offset of the multipliers further away from the center of the coordinate system, leading in the end to a wrong compensation for all pixel, similar to the what we see in the above images. Another possibility could be that the data passing from raspistill to the mmal-layer to the GPU has some quirk. Maybe the yellow line right at the bottom of the image created by the hardware pipeline raises its flag here?

cpixip
Posts: 25
Joined: Mon May 01, 2017 7:56 am

Re: Custom lens shading tables

Tue Nov 28, 2017 7:07 pm

.... continuing experiments with the lens shading option. In order to test my suspicion that the mapping of the data of the ls_table.h is slightly off in the image processing pipeline, I did the following experiment:

I captured a raw image and calculated the corresponding ls_table.h. I than introduced in this calculated table lines of constant multiplier ( 64 = 2x ) just one pixel off the edge of matrix.

Here's how this ls_table.h looks like when viewed as an image:
ls_table_test.png
ls_table_test.png (5.11 KiB) Viewed 1676 times
Note the artificially introduced constant value marker lines, cyan-colored in this display , just one pixel off the edge of the table.

I recompiled the special version of the raspistill with this custom lens shading table and than took a normal jpg (of the same gray card which I used for calculating the ls_table.h). I arrived at the following result:
test_pipeline_cmp.jpg
test_pipeline_cmp.jpg (16.11 KiB) Viewed 1676 times
Certainly the marker lines are not symmetrically with respect to the image border, as one would expect them to be. The right and bottom marker lines are closer to the edge of the frame than the left and top marker lines.

From my experience, I can think of two reasons for that: first, in GPU programming and image processing one has to be careful which coordinate system is used. The center of a pixel is one half unit off the pixel index, at least occasionally (see for example (the following are random Google-picks): https://msdn.microsoft.com/de-de/librar ... s.85).aspx or http://www.flipcode.com/archives/Light_ ... tion.shtml, but read the last comment in this thread: https://www.opengl.org/discussion_board ... -in-OpenGL).

If we imagine just a half-pixel shift of the marker lines up and to the left, at least the marker lines would be symmetrical with respect to the image frame.

A second possibility I have encountered sometimes in my work in image processing is a mix-up of matrix dimensions. The index of a matrix with size N runs (at least in "C") from 0 to N-1. Now, if at some point where N is required a "N-1" is supplied, the matrix might end up being scaled up like it has one row and one column less than the original matrix, i.e., it is scaled too large when applied in texture-mapping.

In this respect, note further the tiny dark orange line just at the lower border of the above image. It is a region of the image where the blue channel drops noticeable with respect to the red and green channels of the image. It is not present in the raw image captured, but an artifact of the lens shading algorithm.

In summary, I think the experiment describe above shows that something in the current version of the custom lens shading does not work correctly. Assuming that this algorithm run on the GPU, I assume something with the texture coordinates is not quite right. It could be either a coordinate offset or a wrong scaling applied to the ls_table.h.

In either case, the pixels do not get their correct multipliers and the lens shading does not really compensate the lens.

In any case - we are close to a very important improvement of the usability of the PI-hardware, so it would be great to get this working!

If somebody wants to replicate these tests, I have included here the ls_table.h matrix I used:

Code: Select all

uint8_t ls_grid[] = {
//R - Ch 3
48, 64, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 50, 49, 49, 49, 48, 47, 47, 46, 46, 45, 45, 45, 45, 45, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 49, 50, 51, 52, 52, 52, 52, 52, 52, 52, 51, 51, 50, 64, 50,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
49, 64, 50, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 49, 49, 48, 48, 47, 47, 46, 45, 45, 44, 44, 44, 44, 44, 45, 45, 45, 45, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 64, 50,
49, 64, 50, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 49, 48, 48, 47, 46, 46, 45, 45, 44, 44, 43, 43, 43, 43, 44, 44, 44, 45, 45, 46, 47, 47, 48, 48, 49, 50, 50, 51, 51, 52, 52, 52, 52, 52, 52, 52, 51, 64, 50,
49, 64, 50, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 49, 48, 47, 47, 46, 45, 45, 44, 44, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 45, 46, 46, 47, 48, 49, 49, 50, 50, 51, 51, 52, 52, 52, 52, 52, 51, 51, 64, 50,
50, 64, 50, 51, 51, 51, 51, 51, 51, 50, 50, 50, 49, 49, 48, 47, 46, 45, 45, 44, 44, 43, 43, 42, 42, 42, 42, 42, 42, 42, 43, 43, 44, 45, 46, 47, 47, 48, 49, 49, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 64, 50,
49, 64, 50, 50, 51, 51, 51, 50, 50, 50, 49, 49, 49, 48, 47, 46, 45, 45, 44, 43, 43, 42, 42, 41, 41, 41, 41, 41, 41, 41, 42, 42, 43, 44, 45, 46, 46, 47, 48, 49, 49, 49, 50, 50, 51, 51, 51, 51, 51, 51, 64, 50,
49, 64, 49, 50, 50, 50, 50, 50, 50, 50, 49, 49, 48, 47, 46, 45, 44, 44, 43, 42, 42, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 42, 42, 43, 44, 45, 46, 47, 47, 48, 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, 64, 49,
49, 64, 49, 49, 50, 50, 50, 49, 49, 49, 49, 49, 48, 47, 46, 44, 44, 43, 42, 41, 41, 41, 40, 40, 39, 39, 39, 40, 40, 40, 40, 41, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49, 49, 49, 49, 49, 50, 50, 49, 64, 49,
49, 64, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 47, 46, 45, 44, 43, 42, 41, 40, 40, 40, 39, 39, 38, 38, 38, 38, 39, 39, 39, 40, 40, 41, 42, 43, 44, 45, 46, 47, 47, 48, 49, 49, 49, 49, 49, 49, 49, 49, 64, 48,
49, 64, 49, 49, 49, 49, 48, 48, 48, 48, 47, 47, 46, 45, 44, 43, 42, 41, 40, 39, 39, 38, 38, 38, 38, 37, 37, 37, 38, 38, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 47, 48, 48, 48, 49, 49, 49, 49, 49, 64, 48,
48, 64, 48, 48, 48, 48, 48, 48, 47, 47, 46, 45, 45, 44, 43, 42, 41, 40, 39, 38, 38, 37, 37, 37, 37, 36, 36, 36, 36, 37, 37, 38, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46, 47, 47, 48, 48, 48, 48, 48, 48, 64, 48,
48, 64, 48, 48, 48, 48, 48, 47, 47, 46, 45, 45, 44, 43, 42, 41, 40, 39, 38, 38, 37, 36, 36, 36, 35, 35, 35, 35, 35, 35, 36, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46, 47, 47, 47, 47, 47, 47, 47, 64, 47,
48, 64, 48, 48, 48, 48, 47, 47, 46, 45, 45, 44, 43, 42, 41, 40, 39, 38, 37, 37, 36, 35, 35, 35, 34, 34, 34, 34, 34, 35, 35, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46, 46, 47, 47, 47, 47, 47, 64, 47,
47, 64, 47, 48, 47, 47, 47, 46, 46, 45, 44, 43, 42, 41, 40, 39, 39, 38, 37, 36, 35, 35, 34, 34, 34, 33, 34, 34, 34, 34, 34, 35, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 45, 45, 46, 46, 46, 47, 47, 64, 47,
47, 64, 47, 47, 47, 47, 46, 46, 45, 44, 43, 42, 41, 41, 40, 39, 38, 37, 36, 35, 35, 34, 34, 33, 33, 33, 33, 33, 33, 34, 34, 34, 35, 36, 36, 37, 38, 40, 41, 42, 42, 43, 44, 45, 45, 45, 46, 46, 46, 46, 64, 47,
46, 64, 47, 47, 47, 46, 46, 45, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 36, 35, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 43, 44, 44, 45, 45, 45, 46, 46, 64, 46,
46, 64, 46, 46, 46, 46, 45, 45, 44, 43, 42, 41, 40, 40, 39, 38, 37, 36, 35, 35, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 43, 44, 44, 45, 45, 45, 45, 64, 46,
46, 64, 46, 46, 46, 46, 45, 45, 44, 43, 42, 41, 40, 39, 38, 38, 37, 36, 35, 34, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 42, 43, 43, 44, 44, 44, 45, 45, 64, 45,
46, 64, 46, 46, 46, 45, 45, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 35, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 35, 35, 36, 37, 38, 39, 40, 41, 42, 42, 43, 44, 44, 44, 44, 45, 64, 45,
46, 64, 46, 45, 45, 45, 44, 44, 43, 42, 41, 40, 39, 39, 38, 37, 36, 35, 34, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 34, 35, 36, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 44, 44, 44, 64, 45,
46, 64, 45, 45, 45, 45, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 36, 35, 34, 34, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 34, 35, 36, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 44, 44, 44, 64, 44,
46, 64, 46, 45, 45, 45, 44, 44, 43, 42, 42, 41, 40, 39, 37, 36, 36, 35, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 35, 36, 36, 37, 38, 39, 40, 41, 41, 42, 43, 43, 44, 44, 44, 45, 64, 45,
46, 64, 46, 46, 45, 45, 44, 44, 43, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42, 42, 43, 44, 44, 44, 44, 45, 64, 45,
46, 64, 46, 46, 45, 45, 45, 44, 44, 43, 42, 41, 40, 39, 39, 38, 36, 36, 35, 34, 34, 33, 33, 32, 32, 32, 32, 32, 33, 33, 33, 33, 34, 35, 35, 36, 37, 38, 39, 40, 40, 41, 42, 42, 43, 44, 44, 44, 45, 45, 64, 45,
46, 64, 46, 46, 45, 45, 45, 45, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 35, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 35, 35, 36, 37, 37, 38, 39, 40, 41, 42, 42, 43, 43, 44, 44, 44, 45, 45, 64, 45,
46, 64, 46, 46, 45, 45, 45, 44, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 36, 35, 35, 34, 34, 33, 33, 33, 33, 33, 33, 34, 34, 34, 35, 36, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 44, 44, 44, 45, 45, 45, 64, 45,
46, 64, 46, 46, 46, 45, 45, 45, 44, 43, 43, 42, 41, 40, 39, 39, 38, 37, 36, 36, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 36, 37, 37, 38, 39, 40, 41, 42, 42, 43, 44, 44, 44, 45, 45, 45, 45, 64, 45,
46, 64, 46, 46, 46, 46, 45, 45, 44, 44, 43, 42, 41, 40, 40, 39, 38, 37, 37, 36, 36, 35, 35, 34, 34, 34, 34, 34, 34, 34, 35, 35, 36, 37, 37, 38, 39, 40, 40, 41, 42, 43, 44, 44, 44, 45, 45, 45, 46, 46, 64, 45,
46, 64, 46, 46, 46, 46, 46, 45, 45, 44, 43, 42, 42, 41, 40, 39, 39, 38, 37, 37, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36, 37, 38, 39, 39, 40, 41, 42, 43, 44, 44, 44, 45, 45, 46, 46, 46, 46, 64, 45,
46, 64, 46, 46, 46, 46, 46, 46, 45, 44, 44, 43, 42, 41, 41, 40, 39, 38, 38, 37, 37, 36, 36, 36, 35, 35, 35, 35, 35, 36, 36, 37, 37, 38, 39, 39, 40, 41, 42, 42, 43, 44, 45, 45, 45, 46, 46, 46, 46, 46, 64, 45,
47, 64, 46, 46, 47, 46, 46, 46, 46, 45, 44, 44, 43, 42, 41, 41, 40, 39, 38, 38, 37, 37, 37, 36, 36, 36, 36, 36, 36, 37, 37, 38, 38, 39, 39, 40, 41, 41, 42, 43, 44, 45, 45, 46, 46, 46, 47, 47, 47, 46, 64, 46,
47, 64, 47, 47, 47, 47, 47, 46, 46, 45, 45, 44, 44, 43, 42, 41, 40, 40, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 43, 44, 45, 45, 46, 46, 46, 47, 47, 47, 47, 46, 64, 46,
47, 64, 47, 47, 47, 47, 47, 47, 46, 46, 45, 45, 44, 44, 43, 42, 41, 40, 40, 40, 39, 39, 39, 38, 38, 38, 38, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 44, 45, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 64, 46,
47, 64, 47, 47, 47, 47, 47, 47, 46, 46, 46, 45, 45, 44, 44, 43, 42, 41, 41, 40, 40, 40, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 41, 41, 42, 43, 43, 44, 44, 45, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 64, 46,
46, 64, 47, 47, 47, 47, 47, 47, 46, 46, 46, 45, 45, 45, 44, 43, 43, 42, 42, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 46, 46, 46, 47, 47, 47, 48, 48, 47, 47, 47, 64, 46,
46, 64, 46, 46, 47, 47, 47, 47, 47, 46, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 42, 42, 42, 43, 44, 44, 45, 46, 46, 46, 46, 47, 47, 47, 48, 47, 47, 47, 47, 64, 46,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
45, 64, 45, 46, 46, 46, 47, 47, 46, 46, 46, 46, 45, 45, 44, 44, 44, 43, 43, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 42, 42, 42, 43, 43, 44, 44, 44, 45, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 64, 45,
//Gr - Ch 2
51, 64, 53, 53, 54, 54, 54, 55, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 57, 57, 57, 56, 56, 55, 64, 54,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
52, 64, 53, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 53, 53, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 58, 58, 57, 57, 57, 57, 56, 56, 64, 55,
52, 64, 53, 54, 54, 54, 54, 54, 54, 55, 54, 54, 54, 54, 53, 53, 52, 52, 52, 52, 52, 51, 51, 50, 51, 51, 51, 51, 52, 52, 52, 52, 53, 53, 54, 54, 55, 55, 55, 55, 56, 57, 57, 57, 57, 57, 57, 57, 56, 55, 64, 55,
52, 64, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 52, 52, 51, 51, 51, 50, 50, 50, 49, 49, 49, 50, 50, 50, 50, 50, 51, 52, 52, 52, 53, 53, 54, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 56, 55, 64, 55,
52, 64, 53, 53, 54, 54, 54, 54, 54, 53, 53, 53, 53, 52, 52, 52, 51, 50, 50, 49, 49, 49, 49, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 51, 52, 52, 53, 53, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, 55, 64, 55,
52, 64, 52, 53, 54, 54, 53, 53, 53, 53, 53, 53, 52, 51, 50, 50, 49, 49, 48, 48, 48, 47, 47, 47, 46, 46, 46, 47, 47, 47, 47, 48, 48, 49, 50, 50, 51, 52, 52, 53, 53, 54, 54, 55, 55, 55, 55, 55, 55, 55, 64, 54,
52, 64, 52, 52, 53, 53, 53, 53, 53, 53, 52, 52, 51, 50, 49, 49, 48, 48, 47, 47, 46, 46, 46, 45, 45, 44, 45, 45, 45, 46, 46, 46, 47, 48, 48, 49, 50, 51, 52, 52, 53, 53, 54, 54, 54, 55, 55, 55, 55, 54, 64, 54,
52, 64, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 50, 49, 48, 47, 47, 46, 45, 45, 44, 44, 44, 44, 43, 43, 43, 44, 44, 44, 44, 45, 45, 46, 47, 48, 49, 50, 51, 52, 52, 52, 53, 53, 54, 54, 54, 54, 54, 54, 64, 53,
52, 64, 52, 52, 52, 52, 52, 52, 51, 51, 51, 50, 49, 48, 47, 46, 45, 44, 44, 43, 43, 42, 42, 42, 41, 41, 41, 42, 42, 42, 43, 43, 44, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 53, 53, 53, 53, 53, 53, 64, 53,
51, 64, 51, 52, 51, 52, 51, 51, 50, 50, 49, 49, 48, 47, 46, 45, 44, 43, 42, 42, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 41, 41, 42, 43, 44, 44, 46, 47, 48, 49, 50, 51, 52, 52, 52, 53, 53, 53, 53, 53, 64, 52,
51, 64, 51, 51, 51, 51, 51, 50, 50, 49, 48, 48, 47, 46, 44, 44, 43, 42, 41, 40, 40, 39, 39, 39, 39, 38, 38, 39, 39, 39, 39, 40, 40, 41, 42, 43, 44, 45, 46, 48, 49, 50, 51, 51, 52, 52, 52, 52, 52, 52, 64, 52,
51, 64, 51, 51, 51, 50, 50, 49, 49, 48, 47, 47, 46, 44, 43, 42, 41, 40, 39, 39, 38, 38, 38, 37, 37, 37, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 49, 50, 51, 51, 52, 52, 52, 52, 64, 51,
51, 64, 51, 51, 50, 50, 49, 49, 48, 47, 46, 46, 45, 44, 42, 41, 40, 39, 39, 38, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 38, 38, 39, 40, 42, 43, 44, 46, 47, 48, 49, 49, 50, 50, 51, 51, 51, 51, 64, 52,
50, 64, 50, 50, 50, 49, 49, 49, 48, 47, 46, 45, 44, 43, 41, 40, 39, 39, 38, 37, 36, 35, 35, 35, 35, 34, 35, 35, 35, 35, 35, 36, 36, 37, 38, 39, 40, 42, 44, 45, 46, 47, 48, 49, 49, 50, 50, 51, 51, 51, 64, 52,
49, 64, 49, 50, 50, 49, 49, 48, 47, 46, 45, 44, 43, 42, 41, 39, 38, 38, 37, 36, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 36, 36, 37, 38, 40, 41, 43, 44, 45, 46, 47, 48, 49, 49, 49, 50, 50, 51, 64, 51,
49, 64, 49, 49, 49, 49, 48, 47, 47, 46, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 35, 34, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 35, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 48, 48, 49, 49, 49, 50, 50, 64, 50,
49, 64, 49, 49, 49, 49, 48, 47, 46, 45, 44, 43, 42, 40, 40, 38, 37, 36, 35, 35, 34, 33, 33, 33, 32, 32, 33, 33, 33, 33, 33, 34, 34, 35, 36, 37, 38, 40, 41, 42, 44, 45, 46, 47, 48, 48, 49, 49, 49, 50, 64, 50,
49, 64, 49, 49, 49, 48, 48, 47, 46, 45, 44, 42, 41, 40, 39, 38, 37, 36, 35, 34, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 35, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49, 49, 64, 50,
49, 64, 49, 49, 48, 48, 48, 47, 46, 45, 44, 42, 41, 40, 39, 38, 36, 36, 35, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 34, 34, 35, 36, 38, 39, 40, 41, 43, 44, 45, 46, 47, 47, 48, 48, 49, 49, 64, 49,
49, 64, 48, 48, 48, 48, 47, 46, 45, 44, 43, 42, 40, 39, 38, 37, 36, 35, 34, 34, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 35, 36, 37, 39, 40, 41, 42, 44, 44, 45, 47, 47, 48, 48, 49, 49, 64, 49,
49, 64, 48, 48, 48, 47, 47, 46, 45, 44, 43, 42, 40, 39, 38, 37, 36, 35, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 35, 36, 37, 38, 40, 41, 42, 44, 45, 46, 46, 47, 48, 48, 49, 49, 64, 49,
48, 64, 48, 48, 48, 47, 47, 46, 45, 44, 43, 42, 41, 40, 38, 37, 36, 35, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 34, 34, 35, 36, 37, 39, 40, 41, 42, 44, 45, 45, 46, 47, 48, 48, 49, 49, 64, 49,
48, 64, 48, 48, 48, 48, 47, 46, 46, 44, 44, 42, 41, 40, 39, 37, 36, 35, 34, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 35, 35, 36, 38, 39, 40, 41, 42, 44, 45, 46, 47, 47, 48, 48, 49, 49, 64, 49,
49, 64, 48, 48, 48, 48, 47, 47, 46, 45, 44, 43, 42, 40, 39, 38, 37, 36, 35, 35, 34, 33, 33, 32, 32, 32, 32, 33, 33, 33, 33, 34, 35, 35, 36, 37, 38, 39, 40, 41, 43, 44, 45, 46, 47, 48, 48, 48, 49, 49, 64, 49,
49, 64, 48, 48, 48, 48, 47, 47, 46, 45, 44, 44, 42, 41, 40, 39, 38, 37, 36, 35, 35, 34, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49, 49, 64, 49,
48, 64, 48, 48, 48, 48, 47, 47, 46, 45, 45, 44, 43, 41, 40, 39, 38, 37, 36, 36, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 36, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 47, 47, 48, 48, 49, 49, 49, 64, 49,
49, 64, 48, 48, 48, 48, 47, 47, 46, 45, 45, 44, 43, 42, 40, 40, 39, 38, 37, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49, 49, 49, 64, 49,
49, 64, 49, 49, 48, 48, 48, 47, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 38, 37, 36, 36, 36, 35, 35, 35, 35, 35, 35, 35, 36, 36, 37, 38, 39, 39, 40, 41, 42, 44, 45, 46, 46, 47, 48, 48, 49, 49, 49, 50, 64, 49,
49, 64, 49, 49, 49, 48, 48, 48, 47, 46, 45, 44, 44, 42, 41, 41, 40, 39, 38, 38, 37, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49, 49, 50, 49, 64, 49,
49, 64, 49, 49, 49, 49, 48, 48, 47, 47, 46, 45, 44, 43, 42, 41, 40, 40, 39, 39, 38, 38, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 39, 40, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49, 50, 50, 50, 50, 64, 49,
49, 64, 49, 49, 49, 49, 49, 48, 48, 47, 46, 46, 45, 44, 43, 42, 41, 41, 40, 40, 39, 39, 39, 39, 38, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49, 50, 50, 50, 50, 50, 64, 50,
49, 64, 49, 49, 49, 49, 49, 49, 48, 48, 47, 46, 46, 45, 44, 43, 42, 42, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 42, 42, 43, 44, 45, 46, 47, 47, 48, 49, 49, 50, 50, 50, 50, 50, 50, 64, 50,
49, 64, 49, 49, 49, 49, 49, 49, 49, 48, 48, 47, 46, 46, 45, 44, 44, 43, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 43, 43, 44, 44, 45, 46, 47, 47, 48, 49, 49, 50, 50, 50, 50, 50, 50, 50, 64, 49,
49, 64, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 47, 47, 46, 45, 45, 44, 44, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 43, 43, 44, 44, 45, 45, 45, 46, 47, 47, 48, 49, 49, 50, 50, 51, 51, 51, 51, 50, 50, 64, 49,
49, 64, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 44, 44, 43, 43, 44, 44, 44, 44, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 49, 50, 50, 51, 51, 51, 51, 51, 50, 64, 49,
48, 64, 48, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 47, 47, 46, 46, 46, 45, 45, 45, 45, 44, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, 47, 47, 48, 48, 49, 49, 49, 49, 50, 50, 51, 51, 51, 51, 50, 50, 64, 49,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
47, 64, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 48, 48, 48, 49, 49, 50, 50, 50, 50, 50, 51, 51, 50, 50, 50, 49, 64, 48,
//Gb - Ch 1
52, 64, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 54, 54, 53, 53, 53, 52, 51, 51, 50, 50, 50, 49, 49, 49, 49, 50, 50, 50, 50, 51, 52, 52, 52, 53, 53, 54, 54, 55, 56, 56, 56, 57, 56, 56, 56, 56, 55, 55, 64, 54,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
53, 64, 54, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 53, 52, 52, 52, 51, 50, 49, 49, 49, 48, 48, 48, 48, 48, 48, 49, 49, 49, 50, 50, 51, 52, 52, 53, 53, 54, 54, 55, 56, 57, 57, 57, 57, 57, 57, 57, 56, 64, 55,
53, 64, 54, 55, 55, 55, 55, 55, 55, 54, 54, 54, 53, 53, 52, 51, 50, 50, 49, 48, 48, 48, 47, 47, 47, 47, 47, 47, 48, 48, 48, 49, 49, 50, 51, 52, 52, 53, 53, 54, 55, 55, 56, 57, 57, 57, 57, 57, 57, 56, 64, 55,
54, 64, 55, 55, 55, 55, 55, 55, 55, 54, 54, 53, 53, 52, 52, 51, 50, 49, 48, 48, 47, 47, 46, 46, 46, 46, 46, 46, 47, 47, 47, 48, 48, 49, 50, 50, 51, 52, 53, 54, 54, 55, 55, 56, 56, 57, 57, 57, 57, 56, 64, 55,
54, 64, 55, 55, 55, 55, 55, 55, 54, 54, 53, 53, 52, 52, 51, 50, 49, 48, 47, 47, 46, 46, 45, 45, 45, 44, 45, 45, 45, 45, 46, 46, 47, 48, 49, 49, 50, 51, 52, 53, 54, 54, 55, 55, 56, 56, 57, 57, 57, 57, 64, 56,
55, 64, 55, 55, 55, 55, 55, 54, 54, 54, 53, 53, 52, 51, 50, 49, 48, 47, 46, 46, 45, 45, 44, 44, 43, 43, 43, 44, 44, 44, 44, 45, 46, 47, 48, 49, 49, 50, 52, 52, 53, 54, 54, 55, 55, 56, 56, 57, 57, 57, 64, 56,
55, 64, 55, 55, 55, 55, 55, 54, 54, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 45, 44, 44, 43, 42, 42, 42, 42, 42, 42, 43, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 54, 55, 55, 56, 56, 56, 57, 57, 64, 55,
55, 64, 55, 55, 55, 55, 55, 54, 54, 53, 53, 52, 51, 49, 48, 47, 46, 45, 44, 43, 42, 42, 42, 41, 41, 40, 41, 41, 41, 42, 42, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 54, 55, 55, 55, 56, 56, 56, 64, 55,
55, 64, 55, 55, 55, 55, 54, 54, 53, 53, 52, 51, 50, 48, 47, 46, 45, 44, 43, 42, 41, 41, 40, 40, 39, 39, 39, 39, 40, 40, 41, 41, 42, 43, 44, 45, 47, 48, 49, 50, 52, 52, 53, 54, 54, 55, 55, 55, 56, 55, 64, 55,
55, 64, 55, 55, 54, 54, 54, 53, 52, 52, 51, 50, 49, 47, 46, 45, 44, 42, 41, 40, 40, 39, 39, 39, 38, 38, 38, 38, 38, 39, 39, 40, 40, 41, 43, 44, 45, 47, 48, 49, 51, 52, 53, 53, 54, 55, 55, 55, 56, 55, 64, 55,
55, 64, 55, 54, 54, 54, 53, 53, 52, 51, 50, 49, 48, 46, 45, 44, 42, 41, 40, 39, 39, 38, 38, 37, 37, 37, 37, 37, 37, 37, 38, 38, 39, 40, 41, 42, 44, 45, 47, 48, 50, 51, 52, 53, 53, 54, 55, 55, 55, 55, 64, 55,
55, 64, 55, 54, 54, 54, 53, 53, 52, 51, 49, 48, 47, 45, 44, 43, 41, 40, 39, 38, 37, 37, 36, 36, 36, 35, 35, 35, 35, 36, 36, 37, 38, 39, 40, 41, 43, 44, 46, 47, 49, 50, 51, 52, 53, 53, 54, 54, 54, 55, 64, 55,
55, 64, 55, 55, 54, 54, 53, 52, 51, 50, 49, 48, 46, 45, 44, 42, 41, 40, 38, 37, 36, 36, 35, 35, 34, 34, 34, 34, 34, 35, 35, 36, 37, 38, 39, 40, 42, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 54, 54, 55, 64, 55,
55, 64, 55, 55, 54, 54, 53, 52, 51, 50, 48, 47, 46, 44, 43, 41, 40, 39, 38, 36, 36, 35, 34, 34, 33, 33, 33, 34, 34, 34, 35, 35, 36, 37, 38, 40, 41, 43, 45, 46, 48, 49, 50, 51, 52, 52, 53, 54, 54, 55, 64, 55,
55, 64, 54, 54, 54, 54, 53, 52, 51, 49, 48, 47, 45, 44, 42, 40, 39, 38, 37, 36, 35, 34, 34, 33, 33, 33, 33, 33, 33, 34, 34, 35, 36, 36, 38, 39, 40, 42, 44, 45, 47, 48, 50, 51, 52, 52, 53, 53, 54, 54, 64, 55,
55, 64, 54, 54, 54, 53, 53, 52, 50, 49, 47, 46, 44, 43, 42, 40, 39, 38, 36, 35, 35, 34, 33, 33, 33, 32, 32, 32, 33, 33, 33, 34, 35, 36, 37, 39, 40, 42, 44, 45, 46, 48, 49, 50, 52, 52, 53, 53, 54, 54, 64, 55,
55, 64, 54, 54, 54, 53, 52, 51, 50, 49, 47, 46, 44, 43, 41, 40, 39, 37, 36, 35, 34, 33, 33, 32, 32, 32, 32, 32, 32, 33, 33, 34, 34, 35, 37, 38, 39, 41, 43, 44, 46, 47, 49, 50, 51, 52, 53, 53, 54, 54, 64, 54,
55, 64, 54, 54, 54, 53, 52, 52, 50, 49, 47, 46, 44, 43, 41, 40, 38, 37, 36, 35, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 35, 36, 38, 39, 40, 42, 44, 46, 47, 48, 49, 51, 52, 52, 53, 53, 54, 64, 54,
55, 64, 54, 54, 54, 53, 52, 52, 50, 49, 47, 45, 44, 42, 41, 39, 38, 37, 35, 35, 34, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 37, 39, 40, 42, 44, 45, 47, 48, 49, 50, 51, 52, 52, 53, 53, 64, 54,
54, 64, 54, 54, 53, 52, 52, 51, 49, 48, 47, 45, 44, 42, 40, 39, 38, 36, 35, 34, 34, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 37, 39, 40, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 53, 53, 64, 54,
54, 64, 54, 53, 53, 52, 52, 51, 49, 48, 47, 45, 44, 42, 40, 39, 38, 36, 35, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 37, 39, 40, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 53, 53, 64, 53,
54, 64, 54, 54, 53, 52, 52, 51, 49, 48, 47, 46, 44, 42, 40, 39, 37, 36, 35, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 35, 36, 37, 39, 40, 42, 43, 45, 46, 48, 49, 50, 51, 52, 52, 53, 53, 64, 54,
54, 64, 54, 54, 53, 53, 52, 51, 50, 48, 47, 46, 44, 42, 41, 39, 38, 36, 35, 35, 34, 33, 33, 32, 32, 32, 32, 32, 32, 33, 33, 34, 34, 35, 36, 38, 39, 41, 42, 44, 45, 46, 48, 49, 50, 51, 52, 52, 53, 54, 64, 54,
54, 64, 54, 54, 53, 53, 52, 51, 50, 49, 47, 46, 45, 43, 41, 40, 38, 37, 36, 35, 34, 34, 33, 32, 32, 32, 32, 32, 33, 33, 33, 34, 35, 36, 37, 38, 40, 41, 42, 44, 45, 47, 48, 49, 50, 51, 52, 52, 53, 54, 64, 54,
54, 64, 54, 53, 53, 53, 52, 51, 50, 49, 48, 47, 45, 43, 42, 40, 39, 38, 37, 36, 35, 34, 33, 33, 33, 33, 33, 33, 33, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 44, 45, 47, 48, 49, 50, 51, 52, 52, 53, 53, 64, 54,
54, 64, 53, 53, 53, 52, 52, 51, 50, 49, 48, 47, 45, 44, 42, 41, 39, 38, 37, 36, 35, 35, 34, 34, 33, 33, 33, 34, 34, 34, 34, 35, 36, 37, 38, 39, 40, 42, 43, 45, 46, 47, 49, 50, 51, 51, 52, 52, 53, 53, 64, 54,
54, 64, 53, 53, 53, 52, 52, 51, 50, 48, 48, 47, 45, 44, 42, 41, 40, 38, 38, 37, 36, 35, 35, 34, 34, 34, 34, 34, 34, 34, 35, 35, 36, 37, 38, 39, 41, 42, 44, 45, 46, 48, 49, 50, 51, 52, 52, 53, 53, 53, 64, 53,
54, 64, 53, 53, 53, 52, 52, 51, 50, 49, 48, 47, 45, 44, 42, 41, 40, 39, 38, 37, 36, 36, 35, 35, 35, 34, 34, 34, 35, 35, 35, 36, 37, 38, 39, 40, 41, 42, 44, 45, 47, 48, 49, 50, 51, 52, 52, 53, 53, 53, 64, 53,
53, 64, 53, 53, 53, 52, 52, 51, 50, 49, 48, 47, 45, 44, 43, 42, 40, 39, 39, 38, 37, 36, 36, 35, 35, 35, 35, 35, 35, 36, 36, 37, 38, 39, 40, 40, 42, 43, 44, 46, 47, 48, 49, 50, 51, 52, 52, 53, 53, 53, 64, 53,
53, 64, 53, 53, 52, 52, 52, 51, 50, 49, 48, 47, 46, 44, 44, 42, 41, 40, 39, 38, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 37, 38, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 53, 53, 64, 53,
53, 64, 53, 53, 52, 52, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 38, 38, 37, 37, 37, 37, 37, 37, 38, 38, 39, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 52, 53, 53, 53, 53, 64, 53,
53, 64, 53, 53, 52, 52, 52, 51, 50, 49, 49, 48, 47, 46, 45, 44, 42, 41, 41, 40, 39, 39, 39, 38, 38, 38, 38, 38, 38, 39, 39, 40, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 52, 53, 53, 53, 64, 53,
53, 64, 53, 52, 52, 52, 52, 51, 51, 50, 49, 48, 47, 46, 46, 44, 43, 42, 42, 41, 40, 40, 40, 39, 39, 39, 39, 39, 39, 40, 40, 41, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 52, 52, 53, 53, 53, 64, 52,
52, 64, 52, 52, 52, 52, 52, 51, 50, 50, 49, 49, 48, 47, 46, 45, 44, 43, 42, 42, 41, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 42, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 51, 52, 52, 52, 53, 52, 52, 64, 52,
52, 64, 52, 52, 52, 52, 51, 51, 50, 50, 49, 49, 48, 47, 46, 46, 45, 44, 43, 43, 42, 42, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 43, 44, 45, 45, 46, 47, 48, 49, 49, 50, 50, 51, 52, 52, 52, 52, 52, 52, 64, 52,
51, 64, 51, 51, 51, 51, 51, 51, 50, 50, 49, 49, 48, 47, 47, 46, 45, 45, 44, 44, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 44, 44, 45, 46, 47, 47, 48, 49, 49, 50, 50, 51, 52, 52, 52, 52, 52, 52, 64, 51,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
49, 64, 50, 50, 50, 50, 51, 50, 50, 50, 49, 49, 48, 48, 47, 46, 46, 45, 45, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 45, 45, 46, 46, 47, 48, 48, 49, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 64, 50,
//B - Ch 0
36, 64, 37, 37, 37, 37, 37, 38, 38, 38, 37, 38, 37, 37, 37, 37, 37, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36, 37, 37, 37, 37, 37, 38, 38, 38, 39, 39, 39, 39, 39, 39, 38, 38, 38, 64, 38,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
37, 64, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 35, 35, 35, 35, 35, 35, 36, 36, 37, 37, 37, 37, 37, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 64, 38,
37, 64, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 35, 35, 35, 35, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 64, 38,
37, 64, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 38, 64, 38,
37, 64, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 64, 38,
37, 64, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 64, 38,
37, 64, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 64, 37,
36, 64, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 33, 33, 34, 34, 34, 34, 34, 34, 34, 35, 35, 36, 36, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 37, 64, 37,
36, 64, 36, 36, 36, 37, 37, 36, 36, 37, 36, 36, 36, 35, 35, 35, 34, 34, 34, 34, 33, 34, 34, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 35, 35, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 64, 37,
36, 64, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 64, 37,
36, 64, 36, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 35, 35, 35, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 64, 37,
36, 64, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 34, 35, 35, 35, 36, 36, 36, 36, 36, 37, 37, 36, 36, 36, 64, 36,
36, 64, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 34, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64, 36,
35, 64, 35, 36, 36, 35, 35, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 64, 36,
35, 64, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 34, 35, 35, 35, 35, 35, 36, 36, 36, 35, 36, 36, 64, 36,
35, 64, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 34, 34, 35, 35, 35, 35, 35, 36, 36, 35, 35, 35, 64, 36,
35, 64, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 64, 35,
35, 64, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 64, 35,
35, 64, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 64, 35,
35, 64, 35, 35, 35, 34, 34, 34, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 64, 35,
35, 64, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 64, 35,
35, 64, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 64, 35,
35, 64, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 64, 35,
35, 64, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 64, 36,
35, 64, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 64, 36,
35, 64, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 64, 36,
35, 64, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 64, 36,
35, 64, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 64, 36,
35, 64, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 64, 36,
35, 64, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 64, 36,
36, 64, 35, 35, 36, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 36, 36, 36, 36, 36, 37, 37, 37, 37, 36, 64, 36,
36, 64, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 64, 36,
36, 64, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 64, 36,
36, 64, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, 35, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 64, 37,
36, 64, 36, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 33, 33, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 64, 37,
35, 64, 35, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 64, 36,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
35, 64, 35, 35, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 64, 36,
};
uint32_t ref_transform = 3;
uint32_t grid_width = 52;
uint32_t grid_height = 39;


cpixip
Posts: 25
Joined: Mon May 01, 2017 7:56 am

Re: Custom lens shading tables

Sat Dec 02, 2017 1:00 pm

Reporting some further tests:

Well, I must conclude that at this point in time, the custom lens shading option is definitely broken.

I did the following test: a) captured an image of a homogeneously lit gray card. b) calculated the appropriate ls_table.h lens shading table. c) compiled a new raspistill and finally d) captured some test images, nearly simultaneously a "normal" jpg and a jpg with the raw image attached.

Now, applying in software the calculated ls_table.h to the captured raw image, and employing a simple whitebalance algorithm as well (to come as close as possible to the appearance of the result of the hardware pipeline shown below), I end up with the following result:
raw_compensated_software.jpg
raw_compensated_software.jpg (95.5 KiB) Viewed 1613 times

This result is actually encouraging. It looks quite ok, safe of some drop in the saturation from center to image edges.

Here's the raw input image (this display is again whitebalanced) for comparison:
raw_image.jpg
raw_image.jpg (64.24 KiB) Viewed 1613 times
Clearly, the computed lens shading correction is mostly doing its job in converting the raw image into something more usable.

Now, if we compare the above results with the result of the Pi hardware, using the same lens compensation, we see that something does not quite work out as intended:
raw_compensated_hardware.jpg
raw_compensated_hardware.jpg (92.16 KiB) Viewed 1613 times
The algorithm is certainly working, modifying the colors, but it does not fully compensate. Again, both results, software and hardware versions, were obtained with the same lens shading table. Note also the yellow-orange line just at the bottom of the hardware image - this line should not be there. I guess it's about half the height of a single "pixel" of the lens shading table, zoomed up to full image resolution.

Well, it would be fantastic if the PI team could look into this! The possibility of applying a lens shading correction will be helpful to all users which replace for a project the standard lens with something else - be it a microscope, a better lens, a telescope mirror or some other optical arrangement....

Fer
Posts: 35
Joined: Tue Feb 21, 2017 10:27 am

Re: Custom lens shading tables

Mon Dec 04, 2017 1:57 pm

it would be fantastic if the PI team could look into this
I second that.
I'm very grateful to PI engineers for having allowed custom lens shading correction, but as cpixip proved above, it seems the code has a few issues.
A fixed firmware/raspistill version would be very welcome. :)

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5664
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Custom lens shading tables

Mon Dec 04, 2017 2:34 pm

With regard your lilac border image, please note from the original post:
It doesn't directly map on to how the Pi pipeline is configured, <snip> There is some interpolation performed, so don't worry unduly over the apparently coarse grid.
Adding a border is not the intended purpose of the lens shading compensation, so I have zero interest in fixing it.
And of course it won't be symmetrical. The image off the sensor is 3280x2464. 3280/64 = 51.25, and 2464/64 = 38.5, so there is going to be an overhang in the grid to both the right and bottom. That is why the grid is 52 elements wide and 39 elements high.
Most of the rest of that post is huge assumptions.

With regard your other images, it half looks like you may have the colour channels swapped. H&V flips are done on the sensor and hence before lens shading, which is why the reference transform is specified in the ls structures. The table has to be flipped appropriately whenever the transform doesn't match the reference. Likewise it gets scaled if using a binned or skipped mode. However all of those transforms are common with the main lens shading configuration, so I don't expect they're at fault.

I have other things on my plate at the moment, but I will look at this again at a later date.
I know some of the handling of the grid at the edges is sub-optimal which may result in the yellow line at the bottom edge, but that's about it.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
Please don't send PMs asking for support - use the forum.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

cpixip
Posts: 25
Joined: Mon May 01, 2017 7:56 am

Re: Custom lens shading tables

Mon Dec 04, 2017 5:50 pm

Ok, I am off.

At the current point in time, the lens shading option as implemented in the Pi hardware is not working. And there is no expectation that this will change in the near future, as the hardware is closed-source and the people who might fix it seem to be too busy to bother.

Specifically,
  • the accompanying lens_shade_analyse.c program has two deficits:
    • it does not sample enough pixels of the raw image for each entry, resulting in a too noisy lens shading table. This leads to unnecessary but quite noticeable low-frequency color noise in the final image.
    • the scaling during the computations of the lens shading table is wrong. This leads to entries in the table with values equal to 31, corresponding to multiplier less than one. These are values the ISP cannot cope with. At the position of these values the ISP typically creates large semi-rectangular patches with bright random colors.
  • the hardware lens shading algorithm does not give satisfactory results, even with a carefully acquired reference image:
    • a lens shading table which works flawlessly on raw images in a software implementation fails if used in the ISP.
    • with the custom lens shading option enabled, a colored line just at the bottom of the jpg-image produced by the ISP appears. This is not the case if the standard lens shading is in operation (i.e., the standard raspistill from the distribution is used). So there is a difference between standard and custom lens shading.
    • the discolored line at the bottom of the output jpg is present in all images, with both both v1- and v2-sensors. Tested however only in full resolution mode, no h- or v-flips, no binning etc.
I will look into other hardware options for my project, as the PI hardware seems too limited to realize more advanced projects.

One final note: the lens shading option might not even be that interesting, as both the v1- and v2-sensors use a microlens array in front of the sensor, tuned by design for a certain range of lenses (with short focal length). If you swap the standard lens with another one, the microlens array on the sensor will not fit that new lens. Because of this, one will get increased crosstalk between pixels (= desaturation of colors) and decreased signal-to-noise ratios (= more noise) in image areas further away from the center of the image. The lens shading algorithm discussed in this thread will not at all be able to counter these image degradations.

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 20477
Joined: Sat Jul 30, 2011 7:41 pm

Re: Custom lens shading tables

Mon Dec 04, 2017 10:39 pm

cpixip wrote:
Mon Dec 04, 2017 5:50 pm
Ok, I am off.

At the current point in time, the lens shading option as implemented in the Pi hardware is not working. And there is no expectation that this will change in the near future, as the hardware is closed-source and the people who might fix it seem to be too busy to bother.

Specifically,
  • the accompanying lens_shade_analyse.c program has two deficits:
    • it does not sample enough pixels of the raw image for each entry, resulting in a too noisy lens shading table. This leads to unnecessary but quite noticeable low-frequency color noise in the final image.
    • the scaling during the computations of the lens shading table is wrong. This leads to entries in the table with values equal to 31, corresponding to multiplier less than one. These are values the ISP cannot cope with. At the position of these values the ISP typically creates large semi-rectangular patches with bright random colors.
  • the hardware lens shading algorithm does not give satisfactory results, even with a carefully acquired reference image:
    • a lens shading table which works flawlessly on raw images in a software implementation fails if used in the ISP.
    • with the custom lens shading option enabled, a colored line just at the bottom of the jpg-image produced by the ISP appears. This is not the case if the standard lens shading is in operation (i.e., the standard raspistill from the distribution is used). So there is a difference between standard and custom lens shading.
    • the discolored line at the bottom of the output jpg is present in all images, with both both v1- and v2-sensors. Tested however only in full resolution mode, no h- or v-flips, no binning etc.
I will look into other hardware options for my project, as the PI hardware seems too limited to realize more advanced projects.

One final note: the lens shading option might not even be that interesting, as both the v1- and v2-sensors use a microlens array in front of the sensor, tuned by design for a certain range of lenses (with short focal length). If you swap the standard lens with another one, the microlens array on the sensor will not fit that new lens. Because of this, one will get increased crosstalk between pixels (= desaturation of colors) and decreased signal-to-noise ratios (= more noise) in image areas further away from the center of the image. The lens shading algorithm discussed in this thread will not at all be able to counter these image degradations.
Good luck finding an alternative platform, I think you might find it rather difficult at anywhere remotely close to the Pi price point.

But in answer to your statements.

We are a very busy development team and since you have no idea what we are working on, your phrase that we cannot be bothered is both rude and insulting.

The lens analyse program is not closed source, if there is a problem with it, you can look at the code and fix it yourself.

Your statements on microlenses, as I have said before, are almost certainly wrong in many respects. The lens shading algorithm in the HW has been successfully used to compensate for a large variety of lenses over the years - this ISP has been used in many mobile phone cameras including the Nokia 808, with its 42MP sensor and Carl Zeiss lens. Did a pretty good job too.

Any deficiencies in lens shading are almost certainly down to the numbers being plumbed in - the standard garbage in garbage out rule. ISP's require a huge amount of 'tuning' to get right. Almost certainly your reference image is inadequate, unless you have access to a image lab (i.e. constant light sources with fixed colour temps and very evenly distributed). Generally the work on tuning (not just lens shading but the entire ISP) requires a expensively fitted out lab - the one at Broadcom cost over £100k IIRC, and its still took a tear to tune bits of the 808. It is possible to do this stuff at home, if you are very careful and know what you are doing, and can convert a room to a lab.

Yes, there are differences between the custom and the standard lens shading. We've tried to minimise them, and there is probably more work to do on it, it'll get done when time allows. We have some very experienced image and camera professionals in the team, but they are very busy.
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Please direct all questions to the forum, I do not do support via PM.

Fer
Posts: 35
Joined: Tue Feb 21, 2017 10:27 am

Re: Custom lens shading tables

Wed Dec 06, 2017 11:01 pm

As we already explained and illustrated, current hardware lens shading shows a few (show-stopping, for us) issues, where a software implementation using *the same correction table* works as intended. Thus we suspect a bug in the shading correction ISP pipeline.
We see it's not a priority, it's understandable, you are busy people and we fully know it.
But it would be important to at least look at the provided examples and aknowledge there may be an issue, even if considered a low priority issue.

As a side note: forgive me, but the fact that the lens shading system "works even with the Nokia 808 Zeiss lens" means absolutely nothing.
That one is still a *mobile camera lens*, with all the inherent design choices.
We are using a totally different lens system here, as already pointed out. Long backfocal distance, large image circle, long focal, etc. etc.
Thanks for reading.

drich
Posts: 23
Joined: Tue Jul 28, 2015 7:36 pm

Re: Custom lens shading tables

Thu Dec 07, 2017 3:36 pm

Didn't see any problem with their implementation, used for many lenses and works as expected (all you have to do is to modify the tables produced by 6by9's tool, or directly make them by hand). The main issue for me is to fine tune the values to get good results on all white balancing modes.

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5664
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Custom lens shading tables

Thu Dec 07, 2017 5:20 pm

I've sat and not replied to this for a few days to cool off.
cpixip wrote:
Mon Dec 04, 2017 5:50 pm
Ok, I am off.

At the current point in time, the lens shading option as implemented in the Pi hardware is not working. And there is no expectation that this will change in the near future, as the hardware is closed-source and the people who might fix it seem to be too busy to bother.

Specifically,
  • the accompanying lens_shade_analyse.c program has two deficits:
    • it does not sample enough pixels of the raw image for each entry, resulting in a too noisy lens shading table. This leads to unnecessary but quite noticeable low-frequency color noise in the final image.
    • the scaling during the computations of the lens shading table is wrong. This leads to entries in the table with values equal to 31, corresponding to multiplier less than one. These are values the ISP cannot cope with. At the position of these values the ISP typically creates large semi-rectangular patches with bright random colors.
It is open source, so you're free to do as you wish with it, improve it, and ideally contribute your improvements back. It was a quick hack together to demonstrate the basics and had known limitations. My main driver is to deal with the closed source bits because only a very few people can, and leave the open source bits as templates that can be developed further by others (as drich has).

The issue of producing values less than 31 was fixed last Wednesday, ie before your big rant. Future firmwares will clip the values too.
cpixip wrote: [*] the hardware lens shading algorithm does not give satisfactory results, even with a carefully acquired reference image:
  • a lens shading table which works flawlessly on raw images in a software implementation fails if used in the ISP.
  • with the custom lens shading option enabled, a colored line just at the bottom of the jpg-image produced by the ISP appears. This is not the case if the standard lens shading is in operation (i.e., the standard raspistill from the distribution is used). So there is a difference between standard and custom lens shading.
  • the discolored line at the bottom of the output jpg is present in all images, with both both v1- and v2-sensors. Tested however only in full resolution mode, no h- or v-flips, no binning etc.
[/list]
I have acknowledged that there appear to be issues. However the number of people using it is likely to be in single or low double digits, which compared to some of the other stuff I'm working on is, I'm afraid, a very small minority.
I had sorted supporting alternative fixed point representations already as it's the sort of thing that fits into spare hours, but getting attacked for supposedly not caring rather reduces the motivation to do anything on it. Digging further into what is going on is likely to be done this side of Christmas, which seeing as everyone had put up with not having any lens shading options until August isn't that extreme.
cpixip wrote:I will look into other hardware options for my project, as the PI hardware seems too limited to realize more advanced projects.
Your choice. Good luck in your ventures.
cpixip wrote:One final note: the lens shading option might not even be that interesting, as both the v1- and v2-sensors use a microlens array in front of the sensor, tuned by design for a certain range of lenses (with short focal length). If you swap the standard lens with another one, the microlens array on the sensor will not fit that new lens. Because of this, one will get increased crosstalk between pixels (= desaturation of colors) and decreased signal-to-noise ratios (= more noise) in image areas further away from the center of the image. The lens shading algorithm discussed in this thread will not at all be able to counter these image degradations.
Almost all sensors comptaible with small SBCs will have micro lenses. Your only approach is likely to be taking a DSLR and modifying that.
Fer wrote:
Wed Dec 06, 2017 11:01 pm
As we already explained and illustrated, current hardware lens shading shows a few (show-stopping, for us) issues, where a software implementation using *the same correction table* works as intended. Thus we suspect a bug in the shading correction ISP pipeline.
We see it's not a priority, it's understandable, you are busy people and we fully know it.
But it would be important to at least look at the provided examples and aknowledge there may be an issue, even if considered a low priority issue.
Part of the issue is that no one has supplied raw files and ls tables that can be analysed here. JPEGs posted to the forums get reduced in size drastically and don't have the raw, and quoted ls_tables are useless without a raw or the sensor/lens combo.
Raw images allow me to feed it through the MMAL ISP component (which supports the same lens shading override parameter) and see for myself what values are being pushed into the hardware registers where. The representation internally does differ from the API exposed, and has been explained things such as binning/skipping modes and flips require the lens shading tables to be manipulated to compensate.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
Please don't send PMs asking for support - use the forum.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5664
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Custom lens shading tables

Thu Dec 07, 2017 5:28 pm

drich wrote:
Thu Dec 07, 2017 3:36 pm
Didn't see any problem with their implementation, used for many lenses and works as expected (all you have to do is to modify the tables produced by 6by9's tool, or directly make them by hand). The main issue for me is to fine tune the values to get good results on all white balancing modes.
Under some conditions lens shading is affected by colour temperature. The tuner does take colour temperature from the AWB algorithm and modifies the table based on it, but exposing that sort of thing to an external API becomes unmanageable.
When I get a chance I'll look into what is involved with updating the lens shading table live, as then the app could update the table when changing awb mode.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
Please don't send PMs asking for support - use the forum.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5664
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Custom lens shading tables

Fri Jan 26, 2018 5:39 pm

Still no raw and calibration images provided to enable me to really debug the issue, therefore it's still not a priority.
If anyone wishes to provide such then I'll revise the priority. I have some improvements (supporting other representations for the tables), but I'm not pushing partial fixes on this.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
Please don't send PMs asking for support - use the forum.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

drich
Posts: 23
Joined: Tue Jul 28, 2015 7:36 pm

Re: Custom lens shading tables

Sun Jun 10, 2018 5:51 pm

Hi, I just updated my tool ( https://github.com/dridri/lens_shading_editor ) to add better controls over lens correction, it also now have a 3D visualizer.
It can now produce very good results.

Just a few things :
- setting channel 2 and 3 ("green-red" and "green-blue") separately is mandatory, at first I thought that setting both to the same values could do the job but this is absolutely wrong.
- I'm using a smoother interpolation by averaging all the pixels in the 64x64 blocks instead of just taking the 3 at the center, this produces a less blocky correction table.
- even with good optimizations, it's really tricky to get a good result, it's mostly caused by the fact that it's almost impossible to take a picture of a "uniformly illuminated scene of constant colour". Manually editing the table (that's why I made this program) is the thing to do (but producing it entirely from scratch is nearly impossible).

@6by9, currently my tool can import the ch1-4.bin files, are you OK by any chance to let me integrate your code (and credits you of course), allowing me to simply open JPEG-RAW images ?


edit: btw, when the correction table is good enough, all the white balance modes work as expected
Last edited by drich on Sun Jun 10, 2018 7:31 pm, edited 1 time in total.

Return to “Camera board”

Who is online

Users browsing this forum: knute and 10 guests