Signup/Sign In

What is a Pixel in Image and how to access or modify it with Python

Posted in Machine Learning   MAY 31, 2023

    So we are going to discuss the pixels in this blog. Pixels are a very much important concept in image processing because everything we are going to play around with the pixels during the image processing. So, we must aware of these concepts clearly before dive into image processing.

    The code of this blog, you can download from this Github link.

    You will get here a python program file (pixelAccess.py) and an image.jpg.

    To run the above code, we have to use the following syntax:

    python pixelAccess.py --image image.jpg

    In the above scenerio, we kept the image and python code in the same folder, so that the direct image name mentioned. But if your image in another folder or directory, then you must specify the full path of the image.

    python pixelAccess.py --image /path/of/the/image

    What is a pixel?

    As we know images are collections of pixels. So pixels are the blocks that help to become the complete image. We can consider the pixels like a colour or the intensity of the image. So, if we are thinking that the whole image is a grid, then every small grid of the big grid has a pixel value.

    Let's understand the above concepts with an image example. Below is an image that has a dimension of 600 * 400 which represents that the below image is 600 columns and 400 rows. We can also understand these like the image is 600 wide and 400 tall. And the total pixels values in the below image is 600 x 400 = 240,000 pixels.

    A photo of white dog

    Figure 1: The image is 600 wide and 400 tall, so the total pixels in the image is 240,000 pixels.

    As we know, most of the images can be represented in two ways either grayscale or colour. So, here we are going to discuss both image types. So the values of the grayscale image in between 0 to 255 where 0 represent the most darken side and 255 represent the most white part of the image. And the values in between makes changes the shades of the grayscale from light to dark or vice-versa.

    Dark to White Colour Grayscale

    Figure 2: The image above shows the darkened side on the left side (value 0) and more white to the right side (value 255).

    Now, we are going to discuss the colour image type.

    The colour image has three colour channels which are Red, Green and Blue and we generally called it is RGB. So every pixel in the colour image is a combination of RGB values. The RGB colour cube image is given below:

    RGB Colour scale Cube

    Figure 3: The colour cube (RGB channel).

    Grayscale and colour are the two most common way to represent the images. So, it does not mean there only exit these two colour spaces. But we currently focus only on these two colour spaces to understand the basis of the colour spaces.

    The RGB colour channel values range is 0 and 255. So each channel has a range from 0 to 255. They darken and the light of the colour depends upon the intensity of the integer value. The 8-bit unsigned integer is used to store the colour value. We filled the colour of the pixel in the tuple form (red, green, blue). When we want to show the full white colour of the image, then we must fill all the colour channel with the value 255 like this: (255, 255, 255). And if we want to show only black colour then we must fill the colour tuple with value 0 like this: (0, 0, 0).

    RGB 255

    Figure 4: In the above image we can see the RGB colours with their bucket values.

    In the above image, we can see that RGB colours and their bucket value. The red colour has a bucket value (255, 0, 0), the green colour has a bucket value (0, 255, 0) and the blue colour has a bucket value (0, 0, 255).

    The black colour in the rectangle has a bucket value (0, 0, 0).

    Here are some samples of different colours:

    • Black: (0, 0, 0)
    • White: (255, 255, 255)
    • Maroon: (128, 0, 0)
    • Navy: (0, 0, 128)
    • Olive: (128, 128, 0)
    • Purple: (128, 0, 128)
    • Teal: (0, 128, 128)
    • Yellow: (255, 255, 0)
    • Red: (255, 0, 0)
    • Green: (0, 255, 0)
    • Blue: (0, 0, 255)
    • Aqua: (0, 255, 255)
    • Fuchsia: (255, 0, 255)

    After understanding the grayscale and colour image pixels value we are going to see how to calculate pixel coordinates.

    Co-ordinates System of the Image

    We as already explained the image is a grid so there will be x,y value which represents the columns and rows respectively. If we move only to the right side then the value of x will be increased and if we move only down then the value of y will be increased. If we move towards the right side and along down then both the x,y values will be increased.

    LED colours in pixel

    Figure 5: The grid representation of the image.

    In the above figure no. 5, we have 6 columns and 5 rows. So the total number of pixels is 6 x 5 = 30 pixels. The topmost left pixel starts at (0, 0) and the last rightmost pixel value is (5, 4). The value starts from zero because the python indexed starts from zero not from one. So that we start the value from (0, 0).

    Method to Access and Manipulate the Pixel

    Till now, we understand the pixel and now we are moving forward to access the pixel value and manipulate the value. So now we are going to code to understand the pixel manipulation.

    So open your code editor and save the file name as pixelAccess.py and start writing the below code that.

    # we importing the necessarily required packages for this program
    import argparse
    import cv2
    
    # we now creating the object of the argumentParser and passing arguments on that
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--image", required=True, help="image path")
    args = vars(ap.parse_args())
    
    # now, we loading the image
    image = cv2.imread(args["image"])
    
    # we access the height and width of the image using the shape library and showing the result
    (h, w) = image.shape[:2]
    cv2.imshow("Original", image)

    Line 1 to 8: We import the packages which we required for our program. We also create the argumentParser object and then pass all the arguments into that.

    Line 11 to 15: We load the image and store it into a local variable image and then we access the shape of the image (height and width) using the image.shape method. And at the last, we display the image on the screen.

    First, we have to understand how the image represents through the OpenCV. OpenCV uses NumPy to represent the image matrix. As we already explained about the image matrix grid before in this blog using x, y values. So if we want to access any image pixel value then we must have to know the location of that x,y value and after that, we can manipulate that pixel value with any other RGB tuple value.

    One more thing to take care of about OpenCV how stores the RGB values. We generally think that the OpenCV stores the RGB values in the same sequence. But actually, it stores the RGB values in the reverse order like BGR (blue, green, red).

    So now questions come to your mind why the OpenCV stores the RGB values in the reverse order and not in the same order because of the efficiency. It's another concept that will be discussed later on another blog. The reason behind to tell you here because we are going to overwrite the RGB values in the coming code section in reverse order to overcome the confusion.

    # we importing the necessarily required packages for this program
    import argparse
    import cv2
    
    # we now creating the object of the argumentParser and passing arguments on that
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--image", required=True, help="image path")
    args = vars(ap.parse_args())
    
    # now, we loading the image
    image = cv2.imread(args["image"])
    
    # we access the height and width of the image using the shape library and showing the result
    (h, w) = image.shape[:2]
    cv2.imshow("Original", image)
    
    # In opencv all images are just like numpy array and stores like a matrix.
    # The top most first pixel we can access through the values of x,y (0, 0) as
    # we already explained before the python index starts from 0 not from 1.
    (b, g, r) = image[0, 0]
    print("Pixel at (0, 0) - Red: {r}, Green: {g}, Blue: {b}".format(r=r, g=g, b=b))
    
    # now, we are going to change the pixel value of (0, 0) to red tuple
    image[0, 0] = (0, 0, 255)
    
    (b, g, r) = image[0, 0]
    print("Pixel at (0, 0) - Red: {r}, Green: {g}, Blue: {b}".format(r=r, g=g, b=b))
    

    Line 20 to 27: After reading the image at line 11 we access the width and height of the image at line 15. Now at line 20, we access the pixel (0, 0) value RGF and stores it in the tuple (b, g, r). After stores it into a tuple we print the value of red, green and blue at line 21.

    In line 24, we replace the tuple values with the values of red only (0, 0, 255) and stores them at the pixel position (0, 0). Now in line 26 and 27, we access the same pixel value which we replace to print either the colours changed or not.

    So, I guess it seems very easy to access the pixel values and manipulate them as we did in the above code.

    Access the Larger Pixels of the Image

    Till now we access the single pixel of the image and manipulates it. Now, the questions come to mind how we can access the larger portions of the pixels at once like rectangular or circle of the image.

    Now open the same file pixelAccess.py into the code editor and add some lines as shown in the below code.

    # we importing the necessarily required packages for this program
    import argparse
    import cv2
    
    # we now creating the object of the argumentParser and passing arguments on that
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--image", required=True, help="image path")
    args = vars(ap.parse_args())
    
    # now, we loading the image
    image = cv2.imread(args["image"])
    
    # we access the height and width of the image using the shape library and showing the result
    (h, w) = image.shape[:2]
    cv2.imshow("Original", image)
    
    # In opencv all images are just like numpy array and stores like a matrix.
    # The top most first pixel we can access through the values of x,y (0, 0) as
    # we already explained before the python index starts from 0 not from 1.
    (b, g, r) = image[0, 0]
    print("Pixel at (0, 0) - Red: {r}, Green: {g}, Blue: {b}".format(r=r, g=g, b=b))
    
    # now, we are going to change the pixel value of (0, 0) to red tuple
    image[0, 0] = (0, 0, 255)
    
    (b, g, r) = image[0, 0]
    print("Pixel at (0, 0) - Red: {r}, Green: {g}, Blue: {b}".format(r=r, g=g, b=b))
    
    # now, we are going to compute the centre of the image, which simply divides the width and height
    # by 2
    (cX, cY) = (w // 2, h // 2)
    
    # As we are using the NumPy array, so we can use the slice method to access the large pixels
    # of the image -- let's grab the top-left corner
    imageTarget = image[0:cY, 0:cX]
    cv2.imshow("Top-Left image Corner", imageTarget)

    Line 1 to 27: We already explained above.

    Lines 31 to 36: Now, we want to access the larger pixel using the slice, so for that, we need to know the centre point of the image. To calculate the centre point of the image we have to just divide the width and height by 2. After that in line 35, we use the slice method to access

    The portion of the image and in the next line we are showing the cropped image.

    Output: The below screenshot showing the result of the above code where we cropped the top-left corner of the image.

    Crop pixels from a photo with command line

    Figure 6: The above screenshot shows the top-left corner cropped image.

    Now, we are extending the above program pixelAccess.py so that you can practice urself with the more slice methods. The above code will be the same till line 36. And after line 36, we are going to add some more slice methods to clearly understand this concept.

    # we importing the necessarily required packages for this program
    import argparse
    import cv2
    
    # we now creating the object of the argumentParser and passing arguments on that
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--image", required=True, help="image path")
    args = vars(ap.parse_args())
    
    # now, we loading the image
    image = cv2.imread(args["image"])
    
    # we access the height and width of the image using the shape library and showing the result
    (h, w) = image.shape[:2]
    cv2.imshow("Original", image)
    
    # In opencv all images are just like numpy array and stores like a matrix.
    # The top most first pixel we can access through the values of x,y (0, 0) as
    # we already explained before the python index starts from 0 not from 1.
    (b, g, r) = image[0, 0]
    print("Pixel at (0, 0) - Red: {r}, Green: {g}, Blue: {b}".format(r=r, g=g, b=b))
    
    # now, we are going to change the pixel value of (0, 0) to red tuple
    image[0, 0] = (0, 0, 255)
    
    (b, g, r) = image[0, 0]
    print("Pixel at (0, 0) - Red: {r}, Green: {g}, Blue: {b}".format(r=r, g=g, b=b))
    
    # now, we are going to compute the centre of the image, which simply divides the width and height
    # by 2
    (cX, cY) = (w // 2, h // 2)
    
    # As we are using the NumPy array, so we can use the slice method to access the large pixels
    # of the image -- let's grab the top-left corner
    imageTarget = image[0:cY, 0:cX]
    cv2.imshow("Top-Left image Corner", imageTarget)
    cv2.waitKey(0)
    
    # Now, as we did before top-left cropped, we are going to do similar way for the
    # top-right, bottom-left and bottom-right and display their results on the screen
    topright = image[0:cY, cX:w]
    bottomright = image[cY:h, cX:w]
    bottomleft = image[cY:h, 0:cX]
    cv2.imshow("Top-Right image", topright)
    cv2.imshow("Bottom-Right image", bottomright)
    cv2.imshow("Bottom-Left image", bottomleft)
    cv2.waitKey(0)

    So Line 1 to 36 is already explained before. Only line 37. we used to pause the screen for a movement to see the result and when we press any key it will move forward.

    Line 41 will crop the top-right corner of the image.

    Line 42 will crop the bottom-right corner of the image.

    Line 43 will crop the bottom-left corner of the image.

    Line 44 to 46: These lines will display the cropped image on the screen with the different window name.

    Line 47 which we already explained that used the pause the screen to see the result.

    Output: After running the above python code, we got different cropped images which are shown in the below screenshot.

    Cut photos into four group of pixels

    Figure 7: The above screenshot shows the different cropped images.

    Now, we learn very well how to access the single pixel value and a particular area of the image. But we didn't see yet, how we can change the colour of the particular area of the pixel which we cropped. So, in the next, we are just going to see that concept.

    So, we are going to use the same code as in the previous pixelAccess.py.

    All the lines will be the same from line 1 to 47. We just added some lines from line 48 to change the colour of the cropped image.

    # we importing the necessarily required packages for this program
    import argparse
    import cv2
    
    # we now creating the object of the argumentParser and passing arguments on that
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--image", required=True, help="image path")
    args = vars(ap.parse_args())
    
    # now, we loading the image
    image = cv2.imread(args["image"])
    
    # we access the height and width of the image using the shape library and showing the result
    (h, w) = image.shape[:2]
    cv2.imshow("Original", image)
    
    # In opencv all images are just like numpy array and stores like a matrix.
    # The top most first pixel we can access through the values of x,y (0, 0) as
    # we already explained before the python index starts from 0 not from 1.
    (b, g, r) = image[0, 0]
    print("Pixel at (0, 0) - Red: {r}, Green: {g}, Blue: {b}".format(r=r, g=g, b=b))
    
    # now, we are going to change the pixel value of (0, 0) to red tuple
    image[0, 0] = (0, 0, 255)
    
    (b, g, r) = image[0, 0]
    print("Pixel at (0, 0) - Red: {r}, Green: {g}, Blue: {b}".format(r=r, g=g, b=b))
    
    # now, we are going to compute the centre of the image, which simply divides the width and height
    # by 2
    (cX, cY) = (w // 2, h // 2)
    
    # As we are using the NumPy array, so we can use the slice method to access the large pixels
    # of the image -- let's grab the top-left corner
    imageTarget = image[0:cY, 0:cX]
    cv2.imshow("Top-Left image Corner", imageTarget)
    cv2.waitKey(0)
    
    # Now, as we did before top-left cropped, we are going to do similar way for the
    # top-right, bottom-left and bottom-right and display their results on the screen
    topright = image[0:cY, cX:w]
    bottomright = image[cY:h, cX:w]
    bottomleft = image[cY:h, 0:cX]
    cv2.imshow("Top-Right image", topright)
    cv2.imshow("Bottom-Right image", bottomright)
    cv2.imshow("Bottom-Left image", bottomleft)
    cv2.waitKey(0)
    
    # now we are going to change the colour of the bottomleft colour of the cropped image to red
    image[cY:h, 0:cX] = (0, 0, 255)
    # Will display the new updated image
    cv2.imshow("After change the pixel colour", image)
    cv2.waitKey(0)
    

    Line 50 to 53: Now in line 50, we are changing the colour of the whole cropped image to Red. And then we are displaying that on the screen to the next line.

    Output: The below screenshot showing the result of the above concept where we changed the image bottom-left corner to the Red.

    Replace some pixels in a photo

    Figure 8: The above screenshot shows the updated image with bottom-left with new colour (Red).

    Conclusion:

    So, in this blog we saw how to access the pixel value of the image and manipulate it. We also seen the concepts to access the big area using the numpy slice method and change the colour of the whole pixel. So now we have enough skills to understand the image processing and computer vision in the coming blogs.

    About the author:
    I am an Artificial Intelligence Engineer. Doing research work in Virtual Reality and Augmented Reality. I would like to write article or share my work with others apart from my professional life.
    Tags:opencvpixelmachine-learning
    IF YOU LIKE IT, THEN SHARE IT
     

    RELATED POSTS