7

I'm trying to create like a bitmap for an image of a letter but I'm not having the desired result. It's been a few days that I started working with images. I tried to read the image, create a numpy array of it and save the content in a file. I wrote the code bellow:

import numpy as np
from skimage import io
from skimage.transform import resize

image = io.imread(image_path, as_grey=True)
image = resize(image, (28, 28), mode='nearest')
array = np.array(image)
np.savetxt("file.txt", array, fmt="%d")

I'm trying to use images like in this link bellow:

Letter "e"

I was trying to create an array of 0's and 1's. Where the 0's represent the white pixels and the 1's represent the black pixels. Then when I save the result in a file I can see the letter format.

Can anyone guide me on how to get this result?

Thank you.

Leonardo Burrone
  • 339
  • 2
  • 5
  • 13

4 Answers4

15

Check this one out:

from PIL import Image
import numpy as np

img = Image.open('road.jpg')
ary = np.array(img)

# Split the three channels
r,g,b = np.split(ary,3,axis=2)
r=r.reshape(-1)
g=r.reshape(-1)
b=r.reshape(-1)

# Standard RGB to grayscale 
bitmap = list(map(lambda x: 0.299*x[0]+0.587*x[1]+0.114*x[2], 
zip(r,g,b)))
bitmap = np.array(bitmap).reshape([ary.shape[0], ary.shape[1]])
bitmap = np.dot((bitmap > 128).astype(float),255)
im = Image.fromarray(bitmap.astype(np.uint8))
im.save('road.bmp')

The program takes an rgb image and converts it in a numpy array. It then splits it in 3 vectors, one for each channel. I uses the color vectors to create a gray vector. After that it comperes elements with 128, if lower than writes 0(black) else is 255. Next step is reshape and save.

road.jpg road.bmp

prometeu
  • 679
  • 1
  • 8
  • 23
  • That helped a lot. Thank you. What if I needed to resize all my bitmaps to 32x32? How could I do it? – Leonardo Burrone Sep 25 '17 at 00:06
  • I would like to resize image to 32x32 or other resolution, without deforming it too much and lose its format. I would like a default resolution so I could create a dataset of these images. – Leonardo Burrone Sep 25 '17 at 00:31
  • Glad it worked out. Sorry, I don't have this answer. I myself am using tensorflow and I have little experience with opencv. I don't know if it's worth it for you but I would suggest that you choose a library that covers your needs, stick to it and if you encounter problems ask in stackoverflow. Have fun :) – prometeu Sep 25 '17 at 05:50
  • Just one more question. I tried to use the same code for the image https://imgur.com/nSz1Lxd and it didn't work. I get an error about axis. – Leonardo Burrone Sep 25 '17 at 20:08
  • 1
    The image is a two dimmensional array (128, 128), means one channel (not RGB). You can get the shape of the array with `print(ary.shape)`. This is also not a bitmap image; I checked it with `print([elem for elem in range(1,255) if elem in ary]). I updated my answer with some documentation. Hope it helps. – prometeu Sep 26 '17 at 10:37
  • I just ignored the R,G,B split and rewrote like this: https://imgur.com/PyTsZWf. I resized the image and in the end I saved the result in a txt file that has the format of the letter. So if I have an image that I want to create a bitmap I just need to verify if it's a RGB image first? And could you tell me what are the numbers used to multiply on lambda? – Leonardo Burrone Sep 28 '17 at 03:22
  • I don't know. It's just a function from internet. Please ask another question in stackoverflow. Comment are not to be used as a chat. Stackoverflow has chat rooms also. – prometeu Sep 28 '17 at 15:06
  • 2
    The `list(map(lambda x: 0.299*x[0]+0.587*x[1]+0.114*x[2], zip(r,g,b)))` can be done much faster in numpy. It is simply `0.299 * r + 0.587 * g + 0.114 * b`. Otherwise, a very nice answer. – zvone Oct 17 '20 at 13:00
6

You can use pillow

from PIL import Image

img = Image.open("haha.jpg")
img = img.tobitmap()
Aadish Goel
  • 451
  • 1
  • 4
  • 12
1

It takes three steps to do it. First convert original image to a list of pixels. Second change every pixel to either black(0,0,0) or white(255,255,255). Third convert the list back to image and save it.

code:

from PIL import Image

threshold = 10

# convert image to a list of pixels
img = Image.open('letter.jpg')
pixels = list(img.getdata())

# convert data list to contain only black or white
newPixels = []
for pixel in pixels:
    # if looks like black, convert to black
    if pixel[0] <= threshold:
        newPixel = (0, 0, 0)
    # if looks like white, convert to white
    else:
        newPixel = (255, 255, 255)
    newPixels.append(newPixel)

# create a image and put data into it
newImg = Image.new(img.mode, img.size)
newImg.putdata(newPixels)
newImg.save('new-letter.jpg')

threshold is what decides a pixel being black or white, as you can see it the code. Threshold of 50 looks like this enter image description here, threshold of 30 looks like this enter image description here, threshold of 10 looks like this enter image description here, if you tune it down to 5, the output starts to lose pixels: enter image description here.

Yuan Fu
  • 191
  • 2
  • 15
-1

Using PIL

from PIL import Image
Image.open("sample1.png").save("sample1.bmp")
aravinda_gn
  • 1,263
  • 1
  • 11
  • 20