Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Downsampling of images in hdr_debvec( ) is not as good as sampling individual pixels from them #1

Closed
legel opened this issue May 21, 2020 · 6 comments

Comments

@legel
Copy link

legel commented May 21, 2020

Greetings!

Thanks for this implementation, I find that it successfully achieved what the OpenCV version currently does not, specifically with respect to proper weighting of saturated pixels.

To support, after some research, I have found an improvement.

Basically, for the current hdr_debvec( ) function, I kept on getting nasty response functions like this:
response-curve_1

I realized that what is technically happening is downsampling of the pixel values, such that the pixels are averaged / interpolated across each other. This is very problematic in the case where the user has many, many saturated pixels: averaging these values will make them unsaturated, and create a false color in between.

I figured a more robust approach would be to instead just uniformly sample individual pixels across a grid of the image.

Here is how that changed my camera response function (3600 samples):
response_curve_3600samples

Here is the new implementation (not my best code but it works):

def hdr_debvec(img_list, exposure_times, number_of_samples_per_dimension=60):
    B = [math.log(e,2) for e in exposure_times]
    l = constant.L
    w = [z if z <= 0.5*255 else 255-z for z in range(256)]

    samples = []
    width = img_list[0].shape[0]
    height = img_list[0].shape[1]
    width_iteration = width / number_of_samples_per_dimension
    height_iteration = height / number_of_samples_per_dimension

    w_iter = 0
    h_iter = 0

    Z = np.zeros((len(img_list), number_of_samples_per_dimension*number_of_samples_per_dimension))
    for img_index, img in enumerate(img_list):
        h_iter = 0
        for i in range(number_of_samples_per_dimension):
            w_iter = 0
            for j in range(number_of_samples_per_dimension):
                if math.floor(w_iter) < width and math.floor(h_iter) < height:
                    pixel = img[math.floor(w_iter), math.floor(h_iter)]
                    Z[img_index, i*j] = pixel
                w_iter += width_iteration
            h_iter += height_iteration
    
    return response_curve_solver(Z, B, l, w)

Thanks again and great work.

@SSARCandy
Copy link
Owner

Thanks for your research! 💯

If you have time, let's create a merge request so that you can contribute to the project.

@legel
Copy link
Author

legel commented May 22, 2020

Cool, done.

@legel legel closed this as completed May 22, 2020
@ssdutHB
Copy link

ssdutHB commented Jan 14, 2021

Is there a bug in Z[img_index, i*j] = pixel ? Since there will be several cases where different combination of i and j leads to same position of i*j.

@legel
Copy link
Author

legel commented Jan 14, 2021

@ssdutHB I think you may be right. I guess it should be Z[img_index, i * number_of_samples_per_dimension + j] = pixel.

@ssdutHB
Copy link

ssdutHB commented Jan 14, 2021

@ssdutHB I think you may be right. I guess it should be Z[img_index, i * number_of_samples_per_dimension + j] = pixel.

Thank you for your kind and quick reply.

@SSARCandy
Copy link
Owner

cool, i'll fix it.

SSARCandy added a commit that referenced this issue Jan 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants