Pergunta

I'm trying to make a program with a GUI (most likely using Kivy) in Python to match the exposure of two images. I want to display both images (RGB or grayscale) side by side with their corresponding histograms and have a slider to be able to control the exposure on the selected image. I would like some advise on how to go about this.

So far I have read several posts and there seem to be several ways to approach calculating the histogram of an image (numpy, matplotlib, openCV, and PIL), however I'm confused about which would be best (least libraries/dependencies to install) for me to implement. I have also read about changing the exposure on an image and some people mention changing brightness and contrast, so you need to change both to change exposure? I know openCV has equalizeHist but that does it automatically and what I would like is for both images to have as close as possible overall exposure; that's why I was thinking of doing it manually. It would be great if could do it automatically, but I'm still thinking on how to do it.

I know you guys place tremendous value on your time so I'll understand if you don't have time to answer this in depth.

Foi útil?

Solução

We have an example of histogram adjustment here

It sounds as though you are interested in histogram matching, though. I have some code for that purpose here, but it is not well tested.

If you do find that code useful, feel free to make a pull request to scikit-image and we can try to integrate it into the package.

EDIT 2019-04-29: Histogram matching is now included in scikit-image.

Outras dicas

Let's define the exposure term that you use. You can expose bright and dark scenes for say 1 sec and have totally different images. Alternatively, you may want the images have similar contrasts but this doesn't obligatory mean the same exposure.

Since you mentioned histogram equalization, you may eventually equate histograms of two images to make them look equally contrasty. Histogram equalization will make each image histogram look flat so all intensities are equally probable (and thus optimally distributed to maximize the contrast - not always an eye-pleasing effect). You may want to create your own non-flat histogram profiles individually for each image and modify them until the images look as you want them to look.

Here is a pseudo-code: 1. Calculate a histogram of each image: H[i] 2. Sum the histograms as cumulative histograms: C[i] = H[i]+C[i-1] for each image separately; 3. Normalize each one: C[i]/=sum(C(i)) 4. In traditional histogram equalization you remap pixel intensities so that they are equally probable: i2 = 255*C[i1]; in your case you just want them to follow your own histogram profile (so you can have a slider to tweak each image intensity distribution and then compare the results visually); for example, try something like this remapping: i2 = i1*k + 255*C[i1]*(1-k), where the slider changes values of k, from 0.0 to 1.0. When k=1 you get your original image and when k=0 you have full histogram equalization. Below is a histogram equalization function I used for color mapping of Kinect depth that has 10000 levels to 255 levels of gray. You will have to modify and adjust the function for your case.

// histogram equalization
float histEq[10000];
void histEqualize(unsigned short* src, unsigned short* dst, int sz) { 

    if (sz==0)
        return;
    memset(histEq, 0, DEPTH_LEVELS*sizeof(float));

    // 1. depth histogram
    for (int i=0; i<sz; ++i) {
        unsigned short val = src[i];
        if (val!=0 && val < DEPTH_LEVELS)
            histEq[val]++;
    }

    // 2. cumulative histogram
    for (int i=1; i<DEPTH_LEVELS; ++i)
        histEq[i] += histEq[i-1];
    long max_cumul = histEq[DEPTH_LEVELS-1];
    if (max_cumul==0)
        return;

    // 3. mapping function
    for (int i=1; i<DEPTH_LEVELS; ++i)
        histEq[i] = (255*histEq[i])/max_cumul;

    // remap src
    for (int i=0; i<sz; ++i) {
        unsigned short z = src[i];
        if (z>0)
            dst[i] = (unsigned char)(255-histEq[src[i]]+0.5f);
        else
            dst[i] = 0;

    }

} // histEqualization()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top