Intro to Image processing in Python with pillow
Tags: python, tutorial, machinelearning, datascience
Published: 2020-10-25 23:44:39

## Intro to Pillow 

[Pillow]( https://pillow.readthedocs.io/en/stable/) is *Python Imaging Library* that is free and open-source an additional library for the **Python** programming language that adds support for *opening*, *manipulating*, and *saving* in a variety of extension.

### Let’s get started
The most important class in the **Python Imaging Library** is the **Image** class, defined in the module with the same name.

We use *open ( )* to **open** image in our *local directory* as shown below;

```python
>>> from PIL import Image
>>> sample = Image.open('sample.jpg')
```

That’s simple, you have already read an image with **pillow**, you can now do something **image processing** with it, You can also check the type of the image we just loaded;

```python
>>> type(sample)
<class 'PIL.JpegImagePlugin.JpegImageFile'>
```

You can view your **image property** such *format*, *size*, and *color mode* as shown below

```python​
>>> sample.format
'JPEG'
>>> sample.size
(250, 283)
>>> sample.mode
'RGB'
```

Also, you can  **display** the **image** you have just read to the screen, using the show method

```python
>>> sample.show()
```

### Output 
![hakuna matata.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1603665992109/DkhW8X36D.png)

### Image Format Conversion
Once you are done opening your image with the **pillow library** in one format you can save it again in other formats like from **jpg** to **png** and much more.

For instance, let’s try to write a simple Python program to **convert all images** on your project directory which are in **jpg** format to **png** format.

```python
import os
import sys
from PIL import Image

jpg_images = [image for image in os.listdir() if image.endswith('.jpg')]

for jpg_image in jpg_images:
    try:
        new_name = jpg_image.split('.')[0] + '.png'
        Image.open(jpg_image).save(new_name)
    except IOError as error:
        print('Couldn\'t read {} '.format(jpg_image))
```

Once you run the above code on a project directory consisting of images in jpg format, it gonna open all of them and convert into png just as shown below, you could repeat the same process for other conversions.

### Image Cropping
**Pillow** can also be used to perform **image cropping** whereby you can *extract* a *sub rectangle* of a given image by specifying *coordinates* of the sub rectangle.

Therefore before you perform **cropping**, you might wanna know the area of the rectangle to get a **pair** of coordinates you would like crop, you can easily observe them by showing to the screen.

```python 
>>> from PIL import Image
>>> picture = Image.open('sample.png')
>>> cord = (50, 50, 300, 300)
>>> new_picture = picture.crop(cord)
>>> new_picture.show()
```
### Output 


![cropping.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1603666608767/Q2SwHmuKy.png)

As we can see the image has been successful cropped. The coordinates of the surface to be cropped are represented by a **diagonal coordinates**.

Whereby the first two-point is **(x, y)** from the upper left diagonal point and next two-point **(x2, y2)** are also the diagonal point from the bottom right.

### Geometrical Transformation
With **pillow** we can perform some **geometrical** transformation on our image include **resizing** image size and rotations.

This knowledge plays a great role when *generating data* for **deep learning** by transforming one image to form other tons of images from different angles.

### Image resizing 
```python
>>> from PIL import Image
>>> image = Image.open('sample.png')
>>> resized_image = image.resize((200, 200))
>>> resized_image.save('resized.png')
```

When you run the above code you should see a newly resized image on your local directory with a dimension of **200 x 200**.

### Image Rotation

```python
>>> from PIL import Image
>>> image = Image.open('sample.png')
>>> rotated_img = image.rotate(80)
>>> rotated_img.save('rotated_img.png')
```

Use **rotation feature** to generate **360 images** of the *same* picture at different angles, doing this way will help us generate as many as data which you can potentially use to train your **deep learning model**.

### Image generator.py

```python
from PIL import Image 

images = ['sample.jpg']

for img in images:
    try:
        org_img = Image.open(img)
        for angle in range(1, 361):
            image_name = str(angle)+'.jpg'
            new_img = org_img.rotate(angle)
            new_img.save(image_name)
    except IOError:
        print('Couldn\'t read {}'.format(img))
```
After running the above script, you should see **360** images of the same original image at different angles as shown below.


![rotation.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1603667163440/6JXPV1Uwi.png)

### Image Filtering
*Filtering* is a technique for **modifying** or **enhancing** an image. For example, you can **filter** an image to **emphasize** certain features or remove other features. 

**Image filtering**  is useful for many applications including *smoothing*, *sharpening*, *removing noise*, and *edge detection*.

There many filters available on Pillow Library including BLUR, BoxBlur, CONTOUR, FIND_EDGES, Filter, GaussianBlur, Kernel, MaxFilter, MedianFilter, SHARPEN, SMOOTH and etc.

### Example of Usage.

Let’s try finding edges in the below picture using the **FIND_EDGES** filter

- Sample image 

![brain toy.jpeg](https://cdn.hashnode.com/res/hashnode/image/upload/v1603667407979/wHktDMlHt.jpeg)

```python 
>>> from PIL import Image
>>> from PIL import Image, ImageFilter
>>> image = Image.open('brain.jpeg')
>>> edges = image.filter(ImageFilter.FIND_EDGES)
>>> edges.show()
```
### Output 


![edges.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1603667516064/28CRY1ETU.jpeg)

Same wise you can experiments with different **filters** in Python depending on what you’re trying wanna do.

### Reading Image From open file
Also, you can use a pillow to read an Image from a Python file object as shown below;

```python
>>> from PIL import Image
>>> image = Image.open(open('brain.jpeg', 'rb'))
```

### Reading Image from URL
On this you will have to use Pillow in combination with requests, requests will have to send a get **requests** to the server to get the **raw bytes** of image and the pillow will read those bytes.

```python
>>> import requests
>>> from PIL import Image
>>> url = 'https://i1.wp.com/kalebujordan.com/wp-content/uploads/2020/04/code-1084923.png'
>>> raw = requests.get(url, stream=True).raw
>>> Image.open(raw).show()
```

### Output 

![code-1084923.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1603667789044/2qygckFmj.png)

### Creating new Images
With Pillow you can also create a new blank image, of you might need for a variety of purposes, use **Image.new ( )** to generate an entirely new image.

- Syntax
 
```python
new = Image.new(mode, shape, color)
```

- Example of Usage :

```python
>>> from PIL import Image
>>> new_img = Image.new('RGB', (500, 500), 'blue')
>>> new_img.show()
```

![blue.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1603667939701/LGKW83UfS.jpeg)

### Drawing Rectangle on Images
Pillow can also be used to draw Rectangle on Images, this commonly applied on object detection whereby you can draw a rectangular box over a detected object.

-  Example of Usage

Let’s try drawing a rectangular box inside a blank image

```python
>>> from PIL import Image, ImageDraw
>>> new_img = Image.new('RGB', (400, 400), 'black')
>>> pencil = ImageDraw.Draw(new_img)
>>> pencil.rectangle((200, 50, 300, 300), fill ='green')
>>> new_img.show()
```

### Output 

![new.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1603668172847/Ggbdu-ywO.png)

The first two coordinates represent (x,y ) of the left upper diagonal and the next two (x2, y2) represent the coordinate point of the bottom right.

### Drawing Text on Images
We can also use Pillow Library to draw Text on Images

```python 
>>> from PIL import Image , ImageDraw, ImageFont 
>>> new_img = Image.new('RGB', (200, 200), 'black')
>>> font = ImageFont.load_default()
>>> pencil = ImageDraw.Draw(new_img)
>>> pencil.text((100,100),'Hello World',  font=font, fill='blue')
>>> new_img.show()
```

### Output 

![text.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1603668241991/kzQJgk5Of.png)

Well that's all for today, hope you find it useful Now don't be shy, share it with your fellow developer 

The [Original Article](https://kalebujordan.dev/image-processing-with-pillow-2/) can be found on [kalebujordan.dev](https://kalebujordan.dev)

In case of any suggestion, comment, or difficulty drop it in the comment box below and I will get back to you ASAP.

## Related articles 

1. [Essential Pil (Pillow) Image Tutorial (for Machine Learning People)](https://bit.ly/3BVbVpu)