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

I have a problem splitting the 512x512 px image into 64x64 px tiles #208

Closed
Nakilon opened this issue Oct 2, 2019 · 11 comments
Closed

I have a problem splitting the 512x512 px image into 64x64 px tiles #208

Nakilon opened this issue Oct 2, 2019 · 11 comments
Labels

Comments

@Nakilon
Copy link
Contributor

Nakilon commented Oct 2, 2019

$ rbenv install 2.6.3
$ rbenv local 2.6.3
$ gem install vips
$ brew install vips
$ sips -g all data_train/64/1200.png
  pixelWidth: 512
  pixelHeight: 512
  typeIdentifier: public.png
  format: png
  formatOptions: default
  dpiWidth: 72.000
  dpiHeight: 72.000
  samplesPerPixel: 3
  bitsPerSample: 8
  hasAlpha: no
  space: RGB
require "ruby-vips"

img = Vips::Image.new_from_file "data_train/64/1200.png"
img.grid 64, 512/64, 512/64
$ ruby main.rb 
Traceback (most recent call last):
	3: from main.rb:6:in `<main>'
	2: from /Users/nakilon/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/ruby-vips-2.0.15/lib/vips/image.rb:209:in `method_missing'
	1: from /Users/nakilon/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/ruby-vips-2.0.15/lib/vips/operation.rb:326:in `call'
/Users/nakilon/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/ruby-vips-2.0.15/lib/vips/operation.rb:71:in `build': grid: bad grid geometry (Vips::Error)
@jcupitt
Copy link
Member

jcupitt commented Oct 2, 2019

Hi @Nakilon, grid is for rearranging tiles from a very tall, thin image.

Would dzsave fix your problem?

$ vips crop ../k2.jpg x.png 0 0 512 512
$ vips dzsave x.png y --tile-size 64 --overlap 0 --depth one
$ ls y_files/0/
0_0.jpeg  1_0.jpeg  2_0.jpeg  3_0.jpeg  4_0.jpeg  5_0.jpeg  6_0.jpeg  7_0.jpeg
0_1.jpeg  1_1.jpeg  2_1.jpeg  3_1.jpeg  4_1.jpeg  5_1.jpeg  6_1.jpeg  7_1.jpeg
0_2.jpeg  1_2.jpeg  2_2.jpeg  3_2.jpeg  4_2.jpeg  5_2.jpeg  6_2.jpeg  7_2.jpeg
0_3.jpeg  1_3.jpeg  2_3.jpeg  3_3.jpeg  4_3.jpeg  5_3.jpeg  6_3.jpeg  7_3.jpeg
0_4.jpeg  1_4.jpeg  2_4.jpeg  3_4.jpeg  4_4.jpeg  5_4.jpeg  6_4.jpeg  7_4.jpeg
0_5.jpeg  1_5.jpeg  2_5.jpeg  3_5.jpeg  4_5.jpeg  5_5.jpeg  6_5.jpeg  7_5.jpeg
0_6.jpeg  1_6.jpeg  2_6.jpeg  3_6.jpeg  4_6.jpeg  5_6.jpeg  6_6.jpeg  7_6.jpeg
0_7.jpeg  1_7.jpeg  2_7.jpeg  3_7.jpeg  4_7.jpeg  5_7.jpeg  6_7.jpeg  7_7.jpeg
$ vipsheader y_files/0/1_1.jpeg 
y_files/0/1_1.jpeg: 64x64 uchar, 3 bands, srgb, jpegload

@jcupitt
Copy link
Member

jcupitt commented Oct 2, 2019

If this is for training a NN, you can use the new fetch feature in pyvips:

libvips/pyvips#100 (comment)

It's not been added to ruby-vips yet, but should be pretty simple.

@Nakilon
Copy link
Contributor Author

Nakilon commented Oct 2, 2019

Not specifically NN but It's for a contest where you fix the scrambled images like these: 1200

There are hundreds of images in input and dividing them into tiles would produce up to 1024 times more image files. Probably not a big deal for SSD but I'm not sure.

@jcupitt
Copy link
Member

jcupitt commented Oct 2, 2019

Ah OK, yes, I'd think fetch would help a lot there.

I would use fetch to get 16 columns and 16 rows of pixels so that you extract all the edges. Then chop into 64 pixel chunks and do a simple sum-of-squares-of-differences for every possible combination. Put that into a constraint solver and you should get the most likely answer. You're probably doing something very like this already.

@jcupitt
Copy link
Member

jcupitt commented Oct 2, 2019

I made a branch with fetch:

https://github.com/libvips/ruby-vips/tree/add-region-fetch

You can run:

  it 'can fetch pixels from a region' do
    image = Vips::Image.black(100, 100)
    region = Vips::Region.new image
    pixel_data = region.fetch 10, 20, 30, 40

    expect(pixel_data)
    expect(pixel_data.length == 30 * 40)
  end 

The pixel data is a raw memory area, so it'll be RGBRGBRGB etc. bytes in your case. You could just get the green channel first to make it simpler.

@Nakilon
Copy link
Contributor Author

Nakilon commented Oct 2, 2019

You're probably doing something very like this already

Heh, if only it was so easy to do it quickly like in Wolfram Mathematica, but not in my first experience of such with ruby-vips -- a lot of time is spent on directory traversing and filenames concatenations in my scripts. I just made score estimator on the example data to be sure I calculate results correctly, then had to wait until they fix server that stopped working for like an hour ..)

The macOS Spotlight (4 processes in htop) goes mad after I process another folder for these tiles even while indexing is only enabled for Calculator, Programs and System Preferences.

Oh, this fetch thing looks handy and it's surprising that it was not implemented. I don't remember how I was doing such thing before.

@jcupitt
Copy link
Member

jcupitt commented Oct 2, 2019

Yes, file indexing is always annoying :( The first thing I turn off on a new Ubuntu.

fetch is much faster for small areas of pixels, but slower for large images. Anyway, perhaps useful for you.

@Nakilon
Copy link
Contributor Author

Nakilon commented Oct 2, 2019

Just to be sure I use the Region and fetch right, I have to compare my old result with the new one.
For that I need to get a avg of the region. How do I convert Region to Image?

UPD: nvm, Vips::Image.new_from_array region.bytes
Took the same time as the old way with importing presplitted tiles 🎉

@Nakilon
Copy link
Contributor Author

Nakilon commented Oct 3, 2019

(byebug) qq = Vips::Image.new_from_file(src).colourspace "b-w"
#<Image 512x512 uchar, 1 bands, b-w>
(byebug) Vips::Region.new(qq).width
0

Is it ok?

@jcupitt
Copy link
Member

jcupitt commented Oct 3, 2019

>> qq = Vips::Image.new_from_file(src).colourspace "b-w"
#<Image 512x512 uchar, 1 bands, b-w>
>> Vips::Region.new(qq).width
0

Yes, that's correct.

A region is a persistent reference to a rectangular area of pixels in a virtual image.

When you first create it, it has no memory attached to it. fetch executes the pipeline for that area and returns a copy of the computed memory. It'll keep that size and shape until you do another fetch.

@Nakilon Nakilon closed this as completed Oct 3, 2019
@jcupitt
Copy link
Member

jcupitt commented Oct 3, 2019

Glad it's working!

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

2 participants