Search code examples
pythonimagematrixgrayscale

Convert an image to grayscale using only matrix (No BGR2GRAY function) in Python


I'm trying to convert an image to grayscale without using OpenCV or Numpy Example : The matrix of my image is

    [[[116 116 117]
  [115 115 116]
  [117 115 115]
  ..., 
  [135 138 142]
  [137 139 139]
  [137 139 139]]

 [[116 116 116]
  [116 116 116]
  [114 116 116]
  ..., 
  [135 139 140]
  [135 137 138]
  [135 137 138]]

 [[115 118 114]
  [115 118 114]
  [112 116 115]
  ..., 
  [132 141 141]
  [134 137 141]
  [133 136 140]]

 ..., 
 [[ 35  44 163]
  [ 31  40 159]
  [ 10  33 158]
  ..., 
  [ 14  48  53]
  [ 24  56  55]
  [ 27  59  58]]

 [[ 24  38 156]
  [ 19  33 151]
  [  7  28 145]
  ..., 
  [ 25  55  66]
  [ 15  59  61]
  [ 17  61  63]]

 [[  0  27 131]
  [  0  26 130]
  [  0  34 113]
  ..., 
  [ 11  39  55]
  [  6  28  56]
  [  4  26  54]]]

Using the cv2.COLOR_BGR2GRAY function the matrix is :

[[150 150 150 ..., 150 150 150]
[150 173 175 ...,  97  91  89]
[150 176 179 ...,  95  89  82]
..., 
[150  66  67 ..., 152 154 152]
[150  62  59 ..., 152 152 152]
[150  62  64 ..., 155 154 151]]

First, i don't get why it returns a 36 integers when i gave 108 and how can i do it manually

Thanks for your help :)


Solution

  • Question 1

    You are getting 36 integers instead of 108 because your original image had 3 channels (red, green, blue, a.k.a RGB). When you convert it to grayscale, you are flattening it to only one channel. 108 / 3 = 36, seems legit!

    Quesion 2

    Converting it by hand: There are multiple ways to convert an RGB image to grayscale, but the most straightforward would be to take the average of the three channels, basically (red_values + green_values + blue values) / 3. So take your original image array, and run:

    gray_image = (image[:,:,0] + image[:,:,1] + image[:,:,2]) / 3
    

    The above is assuming that your image array is in the form image.shape = (pixel_height, pixel_width, number_of_channels), and that the first 3 channels represent your R,G, and B channels but that's pretty standard