bfraboni / FastGaussianBlur

Fast Gaussian Blur algorithm
89 stars 17 forks source link

Help for implementation? #7

Open davidlamhauge opened 1 year ago

davidlamhauge commented 1 year ago

Hi, This is not a bug report, but an ask for help. I'm working on an FOSS called Pencil2D (www.pencil2d.org). It's a software that is used for traditional, hand drawn 2D animation. The last year I've worked on the camera. The rewrite is almost finished. The only thing missing is depth of field, and for this I need fast gaussian blur. I've looked at your code, and as I understand it, your software must be called via commandline, and saves the resulting image as a file. What I/we need is a c++ class (or function) that can be called, with an image, blur value and maybe more as parameters, and returning the same image, with added blur. I am not sure how to implement it. Could I persuade you to help me implement this? Looking forward to hear from you! Yours, David Lamhauge

bfraboni commented 1 year ago

Hi David,

Thank you for your interest, Pencil2D seems to be an amazing project.

So the implementation of the fast blur is in a single header c++ file, that is the following: https://github.com/bfraboni/FastGaussianBlur/blob/main/fast_gaussian_blur_template.h so it is super easy to add to an existing project, just copy the header file somewhere in the codebase and you should be good to go.

This header contains only one relevant function L.537, which is the following:

//! \brief Utility template dispatcher function for fast_gaussian_blur. Templated by buffer data type T.
//! This is the main exposed function and the one that should be used in programs.
//!
//! \param[in,out] in       source buffer reference ptr 
//! \param[in,out] out      target buffer reference ptr 
//! \param[in] w            image width
//! \param[in] h            image height
//! \param[in] c            image channels
//! \param[in] sigma        Gaussian standard deviation, should be >= 0
//! \param[in] n            number of passes, should be > 0
template<typename T>
void fast_gaussian_blur(T *& in, T *& out, const int w, const int h, const int c, const float sigma, const unsigned int n) 

So if you have direct access to the image buffer you want to blur, you need to:

FYI there is a quick usage example in main.cpp:

    // [...] load the image_data, get its size
    std::size_t size = width * height * channels;
    uchar * new_image = new uchar[size];
    uchar * old_image = new uchar[size];

    // copy input image into the inpu buffer
    for(std::size_t i = 0; i < size; ++i)
    {
        old_image[i] = image_data[i];
    }

    // perform gaussian blur
    // note: the implementation can work on any buffer types (uint8, uint16, uint32, int, float, double)
    // note: both old and new buffer are modified
    fast_gaussian_blur(old_image, new_image, width, height, channels, sigma, passes);

    // convert result
    for(std::size_t i = 0; i < size; ++i)
    {
        image_data[i] = (uchar)(new_image[i]);
    }

Please feel free to reach out if you have any other question. Basile

davidlamhauge commented 1 year ago

Hi Basile, Thank you for your quick answer. It looks easy when you explain it. I hope I can pull it of. I am seltaught when it comes to C++, and we use the Qt environment for development, but it shouldn't pose any problems. Thanks for now, and I'll return if I have any questions. David

bfraboni commented 1 year ago

Hi @davidlamhauge , Did you give it a try ? Let me know if you'd need any help to add this to your software I can help in your codebase directly ! I'm also planning on releasing a new version of the header soon. Basile

davidlamhauge commented 1 year ago

So far I've worked on needed mechanics, to optain depth of field. You should be able to set aperture and distance on the camera, and the artwork layers needed a distance setting as well. All this is needed for calculating the proper blur = sigma. I have thought of one thing though. All images in Pencil2D have 4 channels (RGBA), and I think we only need three passes. Couldn't we just make one special version of fast_gaussian_blur_template.h for this? We don't need to go through that switch at the bottom I think.

davidlamhauge commented 1 year ago

One more thing I forgot about earlier. I couldn't compile the fast_gaussian_blur_template.h because of these two expressions:

std::is_integral_v 
std::conditional_t

You can see the compiler message here: billede If I replace them with std::is_integral and std::conditional it compiles, but can I do that? I don't know what the two functions do?

bfraboni commented 1 year ago

Hi @davidlamhauge ,

Good to hear that your project is moving forward.

Regarding your first question, I could easily make a branch with a dedicated header for 4 channel images - 3 passes only if that could help. Do you also know the type of data used to store the image in advance (uchar, int, float) ? If yes I can also get rid of the template over type.

Regarding your second question:

I use the combination of the two to speed up calculations if the image is store in integral format, and also to rectify integral rounding errors. So in its current form the code required the c++ 17 flag, but I could also make it c++ 11 friendly in the dedicated branch if you need to. Let me know what are your needs.

davidlamhauge commented 1 year ago

Hi @bfraboni , The project is still moving ahead, but slowly. School has started again. I'm reluctant to ask you for a special C++11 version, because I'm not entirely sure about what we need, and what our data types are. As it is now, it's not your code that is giving me problems, so there migth pass a week or two, before I have any news. I'll be back...