libvips / lua-vips

Lua binding for the libvips image processing library
MIT License
125 stars 10 forks source link

Slow operations on spcor result image? #44

Closed RiskoZoSlovenska closed 2 years ago

RiskoZoSlovenska commented 2 years ago

While messing around, I stumbled upon a peculiar occurrence: calling an operation on an image obtained by :spcor() is very slow, but only the first time the operation is called. To illustrate:

local function bench(image, method)
    print(image)

    local start = os.clock()

    image[method](image)

    print(os.clock() - start, "\n")
end

local image1 = Image.new_from_file("test1.png")
local image2 = Image.new_from_file("test2.png")

local image3 = image1:spcor(image2)

bench(image1, "max") -- Fast
bench(image3, "max") -- Slow
bench(image3, "max") -- Fast
bench(image3, "avg") -- Slow
bench(image3, "avg") -- Fast

Output:

test1.png: 1920x1080 uchar, 3 bands, srgb, pngload
0.014

temp-8: 1920x1080 float, 3 bands, srgb, pngload
8.495

temp-8: 1920x1080 float, 3 bands, srgb, pngload
0.00099999999999945

temp-8: 1920x1080 float, 3 bands, srgb, pngload
8.349

temp-8: 1920x1080 float, 3 bands, srgb, pngload
0.001

I'm asking mostly just to satiate my own curiosity (I assume this phenomenon occurs due to some internal technical details), but I'm also wondering if it's possible to mitigate this slowness; the only workaround I've been able to find is to shrink the images before calling :spcor(). I've tried to save the image to file and then read it back into memory, only for the write operation to take ~8 seconds and the resulting :max() on the loaded image to be instant. Casting the image to the uchar format gave me the same results. Trying to load test1.png with sequential access throws an out of order read error, but I assume that's because :spcor() can't work with it.

I'm on version 8.12.1

jcupitt commented 2 years ago

Hello @RiskoZoSlovenska,

Yes, spcor is extremely slow. It's doing a full normalised spatial correlation. There's fastcor if you just need to find the position of something -- it only computes sum of squares of differences.

The speed difference is because of caching. libvips memoises operations, so if you call the same operation with the same arguments on the same image, you get the previous result again.

RiskoZoSlovenska commented 2 years ago

Ah, I see, thanks for the clarification. I guess I was just expecting the :spcor() call itself to be slow. Either way, I think you're right - fastcor should be sufficient for what I'm trying to do. Thanks again for your time.

Slightly unrelated, where's the best place for me to ask these sorts of questions? Should I ask them in this thread, or create new Issues, or go to the Discussions at the libvips repo, or is there some other community server?

jcupitt commented 2 years ago

Yes, libvips is demand-driven, so the spcor is only computed when you use the result.

If questions are specific to Lua, then this is the best place. For general libvips questions, open a discussion in the Q&A section of the libvips site.