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"
so this command will start a local server, we can see that through the above IP in the browser which looks like the below.
now using Browse Files Option we have to select the image which we want to resize.
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.
So this way we can resize an Image using Seam Carving Algorithm and Streamlit in Python.