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

Image Thresholding #1840

Closed
imgifty opened this issue Sep 30, 2020 · 16 comments
Closed

Image Thresholding #1840

imgifty opened this issue Sep 30, 2020 · 16 comments
Labels

Comments

@imgifty
Copy link

imgifty commented Sep 30, 2020

Hello,
I'm working on gigantic '.png' files with dimensions of 100'000x180'000 pixels, which I'd like to process. I would like to threshold the image according to a pixels color value. Is there a better way at doing this, than converting the image to a numpy array and doing the thresholding logic and converting it back into vips format?
The numpy conversion is taking an insane amount of time and memory and I would rather do it only in pyvips.

Is there any other way, I could speed up the whole process by converting all images into a pyramidic file format?

Thanks a lot for the answer and also for the great tool!

@jcupitt
Copy link
Member

jcupitt commented Sep 30, 2020

Hello @imgifty,

Sure, you can do something like:

image = pyvips.Image.new_from_file("huge.png", access="sequential")
image = image > 200
image.write_to_file("huge2.png")

That will make a boolean image with 255 for TRUE (pixel was >200) and 0 for FALSE (pixel was <=200).

If you save with write_to_file("huge2.png", bitdepth=1) it'll save as a one-bit PNG, which would save a lot of space.

PNG is a very slow file format. You could try using TIFF instead with deflate compression. The files are slightly larger, but it's much quicker.

You could also try a different zip library. zlib-ng is supped to be the fastest, I think.

@jcupitt
Copy link
Member

jcupitt commented Sep 30, 2020

You can do more complex thresholding too, eg.:

image = (image > 200).ifthenelse(200, image)

Will make a bool image with the test, then set TRUE pixels to 200 and FALSE pixels back to the image again.

image = (image.gaussblur(5) < image).ifthenelse([255, 0, 0], [0, 255, 0])

Will set pixels greater then the local average red, and pixels less than the local average green.

@imgifty
Copy link
Author

imgifty commented Sep 30, 2020

Hello,
thanks a lot for the quick reply and great info!
Saving as bit image, doesn't seem to work for me. I'm getting a 'bitdepth' KeyError from the pyvips package with version 2.1.12 running the command you suggested up top.

The thresholding has worked perfectly.

Thanks a lot!

@jcupitt
Copy link
Member

jcupitt commented Sep 30, 2020

You probably have an old version of libvips -- PNG 1 bit save was added in 8.10.

Yes, the threshold will be done on the three bands separately. If you want mono output, use something like:

image = image.colourspace('b-w') > 200

ie. convert to mono before thresholding.

@imgifty
Copy link
Author

imgifty commented Sep 30, 2020

Yes, that seems to be the case, as I'm working with libvips 8.4.5 .
One last question, is there any way to count how many pixels adhere to a certain mask?

@jcupitt
Copy link
Member

jcupitt commented Sep 30, 2020

Sure, take the average and multiply by the number of pixels.

@imgifty imgifty closed this as completed Sep 30, 2020
@angstyloop
Copy link

This might be helpful. Did I do this right @jcupitt? Am I doing anything silly?

https://gist.github.com/angstyloop/37d4454442beea452b718bb11469f2a4

@jcupitt
Copy link
Member

jcupitt commented Mar 5, 2023

I would write that C example as: libvips/ruby-vips#243 (comment)

@angstyloop
Copy link

Thanks for responding to the same question twice @jcupitt

I wasn't looking for the right terms when I was searching through the docs. It's really easy now that you've pointed me at those simple relational operations and provided that example.

@angstyloop
Copy link

angstyloop commented Mar 7, 2023

Here's where this ended up. I made a little GTK 3 app that uses the update_image function @jcupitt helped me write. Thanks again! Yay VIPS!

https://gist.github.com/angstyloop/9e8d808570eab3329471e67b71e01f41

vips_gtk_scale_threshold

@jcupitt
Copy link
Member

jcupitt commented Mar 7, 2023

That's very cool! Did you see vipsdisp?

https://github.com/jcupitt/vipsdisp

It's a gtk4 image viewer using libvips. The image is computed with libvips, but rendered to the display using your GPU, so you can pan and zoom at 60fps (hopefully). It has scale and offset sliders (right click, enable the display control bar) which work a little like yours.

The image display is done by tilesource.c, tilecache.c and imagedisplay.c -- it's a widget, so it should be simple to reuse in other applications.

@angstyloop
Copy link

No sir I did not - that's very cool

I'll have to dig into https://github.com/libvips/vipsdisp-tiny soon

If it's not exactly 300 lines I want my money back

@jcupitt
Copy link
Member

jcupitt commented Mar 7, 2023

vipsdisp-tiny is gtk3, but gtk4 is quite a bit different and trickier :( I think something like the vipsdisp image display system is probably the way to do.

vipsdisp-tiny is still interesting to look at though.

@angstyloop
Copy link

angstyloop commented Mar 7, 2023 via email

@jcupitt
Copy link
Member

jcupitt commented Mar 7, 2023

I think the gtk4 in 22.04 is recent enough, you should be OK with that.

Did it work? Try pressing "d" to get the debug display mode where you can see tiles being swapped in and out, it's cute! Hold down "i" for a smooth zoom in on the mouse pointer, "o" for a smooth zoom out. It should be fast even with very large images.

image

Shift cursor left and right should do a smooth and fast screen sized pan.

The info bar is updated in the main GUI thread, unfortunately, so you'll see a bit of hitching unless you turn that off.

@angstyloop
Copy link

angstyloop commented Mar 9, 2023

Works like a charm! Yay vipsdisp!

smooth zoom out

vipsdips_smooth_zoom_out

smooth zoom in

vipsdips_smooth_zoom_in

debug mode (see the tiles)

vipsdips_debug_mode

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants