Open In App

Resize an Image using Seam Carving Algorithm and Streamlit

Last Updated : 16 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

As images continue to dominate our online and offline lives, the need to resize them to meet specific requirements has increased. While conventional resizing techniques such as cropping and scaling are effective, they can lead to distortion and loss of important details. Seam carving, on the other hand, is an algorithmic approach that resizes images while preserving the essential features.

In this article, we will explore how to resize an image using the seam carving algorithm and Streamlit in Python.

Seam Carving 

Seam carving is a content-aware image resizing algorithm that intelligently identifies and removes the least important pixels in an image. Instead of cropping or scaling the image, seam carving selectively removes vertical or horizontal seams of pixels with the least energy, thus preserving the important features of the image.

Seam carving has several advantages over conventional resizing techniques. For one, it allows for non-uniform resizing, which means you can resize an image along its width or height independently. Additionally, it preserves the aspect ratio of the image and reduces distortion, ensuring that the resized image looks natural.

Using Streamlit in Python

Streamlit is an open-source Python library that enables you to create interactive data science applications. It offers a simple and intuitive interface for building web applications, making it an excellent choice for our image resizing project.

To get started, you need to have Python installed on your computer, along with the following libraries:

You can install these libraries using pip, a Python package installer, by running the following command in your terminal:

pip install numpy opencv-python streamlit

Once you have installed the required libraries, you can start building your image-resizing application.

Resizing Images Using Seam Carving and Streamlit

To resize an image using seam carving and Streamlit, you need to perform the following steps:

1. Import the necessary libraries:

Python3




import numpy as np
import cv2
import streamlit as st


2. Create a Streamlit app:

Python3




st.set_page_config(page_title="Seam Carving Image Resizing")
st.title("Seam Carving Image Resizing")


3. Allow the user to upload an image:

Python3




uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"])


4. Load the image and display it:

Python3




if uploaded_file is not None:
    file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
    img = cv2.imdecode(file_bytes, 1)
    st.image(img, channels="BGR")


5. Allow the user to specify the new size of the image:

Python3




new_width = st.slider("New Width", min_value=1, max_value=img.shape[1], value=img.shape[1])
new_height = st.slider("New Height", min_value=1, max_value=img.shape[0], value=img.shape[0])


6. Resize the image using seam carving:

Python3




def seam_carve(img, new_width, new_height):
    for i in range(img.shape[1] - new_width):
        energy_map = np.abs(cv2.Scharr(img, -1, 1, 0)) \
            + np.abs(cv2.Scharr(img, -1, 0, 1))
        energy_map = energy_map.astype(np.float64)
        min_energy_map = np.zeros_like(energy_map)
        min_energy_map[0] = energy_map[0]
        for row in range(1, img.shape[0]):
            for col in range(img.shape[1]):
                if col == 0:
                    min_energy_map[row, col] = energy_map[row, col] \
                        + min(min_energy_map[row - 1, col],
                              min_energy_map[row - 1, col + 1])
                elif col == img.shape[1] - 1:
                    min_energy_map[row, col] = energy_map[row, col] \
                        + min(min_energy_map[row - 1, col - 1],
                              min_energy_map[row - 1, col])
                else:
                    min_energy_map[row, col] = energy_map[row, col] \
                        + min(min_energy_map[row - 1, col - 1],
                              min_energy_map[row - 1, col],
                              min_energy_map[row - 1, col + 1])
        seam_mask = np.ones_like(img[:, :, 0])
        col = np.argmin(min_energy_map[-1])
        for row in reversed(range(img.shape[0])):
            seam_mask[row, col] = 0
            if col == 0:
                col = np.argmin(min_energy_map[row - 1, col:col + 2])
            elif col == img.shape[1] - 1:
                col = np.argmin(min_energy_map[row - 1, col - 1:col + 1]) \
                    + col - 1
            else:
                col = np.argmin(min_energy_map[row - 1, col - 1:col + 2]) \
                    + col - 1
        img = cv2.resize(img, (new_width, new_height))
        seam_mask = cv2.resize(seam_mask, (new_width, new_height))
        for channel in range(img.shape[2]):
            img[:, :, channel] = np.multiply(img[:, :, channel], seam_mask)
        img = img.astype(np.uint8)
  
  
    return img


7. Display the resized image:

Python3




if uploaded_file is not None:
    file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
    img = cv2.imdecode(file_bytes, 1)
    st.image(seam_carve(img, new_width, new_height), channels="BGR")


Now combine all these steps and make one file that can generate output as required.

Final Code

Python3




import cv2
import numpy as np
import streamlit as st
  
  
def seam_carve(img, new_width, new_height):
    img = img.astype(np.float64)
    for i in range(int(img.shape[1] - new_width)):
        energy_map = cv2.cvtColor(img.astype(np.uint8), cv2.COLOR_BGR2GRAY)
        energy_map = cv2.Sobel(energy_map, cv2.CV_64F, 1, 0) ** 2 + \
            cv2.Sobel(energy_map, cv2.CV_64F, 0, 1) ** 2
        min_energy_map = np.zeros_like(energy_map)
        min_energy_map[0] = energy_map[0]
        for row in range(1, energy_map.shape[0]):
            for col in range(energy_map.shape[1]):
                if col == 0:
                    min_energy_map[row, col] = energy_map[row, col] + \
                        min(min_energy_map[row - 1, col],
                            min_energy_map[row - 1, col + 1])
                elif col == energy_map.shape[1] - 1:
                    min_energy_map[row, col] = energy_map[row, col] + min(
                      min_energy_map[row - 1, col - 1],
                      min_energy_map[row - 1, col])
                else:
                    min_energy_map[row, col] = energy_map[row, col] + min(
                      min_energy_map[row - 1, col - 1],
                      min_energy_map[row - 1, col],
                      min_energy_map[row - 1, col + 1])
        seam_mask = np.ones_like(img[:, :, 0])
        col = np.argmin(min_energy_map[-1])
        for row in reversed(range(img.shape[0])):
            seam_mask[row, col] = 0
            if col == 0:
                col = np.argmin(min_energy_map[row - 1, col:col + 2])
            elif col == img.shape[1] - 1:
                col = np.argmin(
                    min_energy_map[row - 1, col - 1:col + 1]) + col - 1
            else:
                col = np.argmin(
                    min_energy_map[row - 1, col - 1:col + 2]) + col - 1
        img = cv2.resize(img, (new_width, new_height))
        seam_mask = cv2.resize(seam_mask, (new_width, new_height))
        for channel in range(img.shape[2]):
            img[:, :, channel] = np.multiply(img[:, :, channel], seam_mask)
        img = img.astype(np.uint8)
    return img
  
  
st.title("Seam Carving Image Resizing")
  
uploaded_file = st.file_uploader(
    "Choose an image...", type=["jpg", "jpeg", "png"])
if uploaded_file is not None:
    img = cv2.imdecode(np.frombuffer(uploaded_file.read(), np.uint8), 1)
    st.image(img, clamp=True, channels="RGB")
    new_width = st.slider("New Width", 100, img.shape[1], img.shape[1])
    new_height = st.slider("New Height", 100, img.shape[0], img.shape[0])
    st.image(seam_carve(img, new_width, new_height),
             clamp=True, channels="RGB")


Output :

1. first we need to make one .py file and add the above code to that file.

2. run this code and go to the command prompt and write the below command

streamlit run "FilePathInComputer"

Terminal OUTPUT

so this command will start a local server, we can see that through the above IP in the browser which looks like the below.

url OUTPUT

now using Browse Files Option we have to select the image which we want to resize.

image picking

after that change width and height slider as required for the new image and press the run button on the top right corner available menu so this will give the new width and height, resized image as below.
 

Final OUTPUT

So this way we can resize an Image using Seam Carving Algorithm and Streamlit in Python.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads