Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - Convert image to a string of pixel values

I have a .jpg image captured from a webcam. It is a greyscale image. I need to convert the image to a string of its pixels like so:

"255 232 45 678 56 23....345 76 44 767 433 345"

How do I go about doing this?

Also, would changing the size of the image change these values?

like image 779
user7091463 Avatar asked Dec 04 '25 14:12

user7091463


1 Answers

Assuming you have the image represented as a numpy array (since the question is tagged as OpenCV related, then this is likely the case), then to obtain the result you want, I'd take the following steps.

  • First flatten the array to make it linear.
  • Then turn it into a regular python list using tolist
  • Convert all the elements into strings using map and str
  • Join all the elements using spaces.

In steps it would look something like

# img is our input image represented by a numpy array
lin_img = img.flatten()
pixel_list = lin_img.tolist()
pixel_str_list = map(str, pixel_list)
img_str = ' '.join(pixel_str_list)

or, put together

# img is our input image represented by a numpy array
img_str = ' '.join(map(str,img.flatten().tolist()))

Let's call this Variant 2 for performance testing purposes.


Update 1

Since numpy arrays are themselves iterable, we can skip the second step.

# img is our input image represented by a numpy array
img_str = ' '.join(map(str,img.flatten()))

Unfortunately it seems that skipping this step has fairly significant negative effect on performance.

Let's call this Variant 3 for performance testing purposes.


Update 2

User Manel Fornos (deleted) answer gave me another idea. Although this approach is a bit hackish, it is somewhat faster.

The gist is to use the existing facilities to get a string represenation of a list, and filter out unwanted characters.

str_rep = str(img.flatten().tolist())
img_str = str_rep.strip('[]').replace(',','')

Let's call this Variant 4 for performance testing purposes.

Variant 1 will be a fixed up version of Liam Lawrence's code:

pxList = ''
# The height and width of your Mat
height = np.size(img, 0)
width = np.size(img, 1)

# Iterates through the values of your Mat and stores them in pxList
for i in range(height): 
    for j in range(width):
        pxList = pxList + " " + str(img[i][j])

pxList = pxList[1:] # Drop the first space

I wrote a simple little script to compare the algorithms (the full code is on pastebin). Here are the results:

# Pixels, Variant 1 (ms), Variant 2 (ms), Variant 3 (ms), Variant 4 (ms)
(1024, 2.8326225819203277, 0.13493335046772717, 1.5932890912113131, 0.09023493209332506)
(4096, 13.339841376487794, 0.5257651461289086, 6.325210327010836, 0.3265428986086241)
(9216, 32.98282323591406, 1.1823080866422975, 14.354809759340927, 0.7088365979475153)
(16384, 75.67087786296861, 2.1013669335069043, 26.917736751458644, 1.2577715882884644)
(25600, 137.34306664673863, 3.3527305844737176, 39.52922089259947, 1.9327700867009523)
(36864, 253.29441311675095, 4.734033934480575, 59.513813906516, 2.9113162427067962)
(50176, 451.560393848939, 6.5756611524649955, 80.0690276278131, 3.998343364868928)
(65536, 730.1453117644841, 8.744634443763166, 103.20875278841335, 5.7598277155337385)
(82944, 1111.2658522242352, 11.029055368769303, 131.75812149309473, 7.009532636131244)
(102400, 1660.044328259597, 13.671936656754369, 163.50234457172607, 8.832774137495392)
(123904, 3752.484254283715, 16.593065599119328, 196.8919234148476, 10.672515640955282)
(147456, 6808.498583618867, 20.05951524565397, 238.21070485215222, 13.339090582743296)
(173056, 11572.846199726502, 23.518125208653373, 275.5151841924039, 15.51396546209105)
(200704, 17107.24135330049, 27.29446060882168, 319.9635533287051, 17.9888784747817)
(230400, 24915.183616213795, 31.83344531218779, 368.9712484407863, 21.44858843792008)
(262144, 34914.46058437594, 36.754758635524354, 423.5016077462319, 24.536341210961155)

Timings (all 4 variants)

Timings (variants 2 and 4)


Update 3

Looking at the timings, one striking issue with Variant 1 is that its performance doesn't scale linearly with the size of input (number of pixels), as one may expect. Instead it looks more like O(n^2). The obvious culprit is the string addition -- since strings in Python are immutable, we keep copying progressively longer and longer strings as we add each pixel value.

One possible way to mitigate this problem is to use the cStringIO module.

output = cStringIO.StringIO()
# The height and width of your Mat
height = np.size(img, 0)
width = np.size(img, 1)

# Iterates through the values of your Mat and stores them in pxList
for i in range(height): 
    for j in range(width):
        output.write(str(img[i][j]) + " ")

output.truncate(output.tell() - 1)
img_str = output.getvalue()

Let's call this Variant 5 for performance testing purposes.

Let's also include Manel Fornos' options, comprehension lists (Variant 6) and generators (Variant 7) for completeness.

# Number of pixels, variants 1..7 (ms)
1024, 2.7356, 0.1330, 1.5844, 0.0870, 2.5578, 1.7027, 1.7354
4096, 13.0483, 0.5250, 6.3810, 0.3227, 10.3566, 6.7979, 6.9346
9216, 34.9096, 1.1787, 14.2764, 0.7047, 23.0620, 15.1704, 15.3179
16384, 72.0128, 2.1126, 25.5553, 1.2306, 41.0506, 27.7385, 28.6510
25600, 142.5863, 3.2655, 40.1804, 1.9044, 64.5345, 42.0542, 42.7847
36864, 265.1944, 4.7110, 57.3741, 2.9238, 94.8722, 62.3143, 61.8108
50176, 444.3202, 6.6906, 78.9869, 4.1656, 126.9877, 82.6736, 84.2270
65536, 739.3482, 8.6936, 101.6483, 5.5619, 163.1796, 110.7537, 111.7517
82944, 1125.0065, 11.1771, 133.8886, 7.0509, 209.9322, 137.3384, 143.7916
102400, 1700.3401, 13.8166, 161.2337, 8.7119, 261.8374, 171.3757, 175.0435
123904, 2304.6573, 16.8627, 196.3455, 10.8982, 314.8287, 205.1966, 210.4597
147456, 5595.0777, 19.8212, 240.1495, 12.9097, 381.7084, 251.7319, 253.3573
173056, 10813.7815, 23.5161, 273.9376, 15.6852, 441.5994, 291.8913, 295.0038
200704, 17561.0637, 27.4871, 322.6305, 17.9567, 517.7028, 340.2233, 342.6525
230400, 25331.5150, 31.6211, 368.3908, 21.0858, 597.7710, 387.3542, 398.9715
262144, 34097.1663, 36.3708, 420.1081, 23.9135, 677.7977, 443.1318, 453.0447

Timings (all 7 variants)

Timings (without variant 1)

like image 94
Dan Mašek Avatar answered Dec 06 '25 05:12

Dan Mašek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!