Search code examples
imagemagick

How to convert a monochrome image to a nxm array of 0 and 1 using imagemagick?


I converted a color jpeg image to a monochrome image using

convert image.jpg -monochrome monochrome.jpg

Now I would like to convert the monochrome.jpg to a text file containing a nxm array with 1s for black pixels and 0s for white pixels (or vice versa). Is this possible with Imagemagick? I tried something like

convert monochrome_800x480.jpg -depth 1 -format 'txt' monochrome.txt

But the output is not a matrix of 1s and 0s as I expected:

# ImageMagick pixel enumeration: 800,480,0,255,gray
0,0: (255)  #FFFFFF  gray(255)
1,0: (255)  #FFFFFF  gray(255)
2,0: (255)  #FFFFFF  gray(255)
3,0: (255)  #FFFFFF  gray(255)
4,0: (255)  #FFFFFF  gray(255)
5,0: (255)  #FFFFFF  gray(255)
6,0: (255)  #FFFFFF  gray(255)
7,0: (255)  #FFFFFF  gray(255)
8,0: (255)  #FFFFFF  gray(255)
...

Solution

  • You can make a 10x4 gradient like this:

    magick -size 10x4 gradient: -monochrome a.png
    

    The nearest I can get to what you want simply is to use NetPBM plain (non-binary) PBM format like this:

    magick a.png -compress none pbm:
    

    Result

    P1
    10 4
    0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 
    1 1 1 1 1 1 1 1 1 1 
    1 1 1 1 1 1 1 1 1 1 
    

    Of course you can strip, or ignore the first two lines with the signature and dimensions. You can also add -negate into the command to invert the brightnesses.

    You will run into a problem though when the width of your image causes more than 70 characters of output as the standard requires lines to never exceed that limit, so you will get more than one output row per image row. That may or may not be a problem.


    One alternative might be vips which can write a CSV format that doesn't have line length issues. That would look like this:

    vips colourspace a.png a.csv b-w
    

    Result

    255     255     255     255     255     255     255     255     255     255
    255     255     255     255     255     255     255     255     255     255
    0       0       0       0       0       0       0       0       0       0
    0       0       0       0       0       0       0       0       0       0
    

    If you want that more compact, you can substitute 255 with 1 and remove tabs like this:

    sed -e 's|255|1|g' -e 's|\t||g' a.csv
    

    Result

    1111111111
    1111111111
    0000000000
    0000000000