|
|
|
import cv2
|
|
import numpy as np
|
|
import streamlit as st
|
|
from PIL import Image
|
|
import os
|
|
import zipfile
|
|
|
|
def detect_nose_and_realistically_thicken(image):
|
|
|
|
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
|
|
nose_cascade = cv2.CascadeClassifier('haarcascade_mcs_nose.xml')
|
|
|
|
|
|
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
|
|
|
|
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
|
|
|
|
for (x, y, w, h) in faces:
|
|
|
|
face_region = gray[y:y+h, x:x+w]
|
|
noses = nose_cascade.detectMultiScale(face_region, 1.3, 5)
|
|
|
|
for (nx, ny, nw, nh) in noses:
|
|
|
|
nose_region = image[y+ny:y+ny+nh, x+nx:x+nx+nw]
|
|
|
|
|
|
thicken_factor = 1.5
|
|
new_width = int(nw * thicken_factor)
|
|
|
|
|
|
thickened_nose = cv2.resize(nose_region, (new_width, nh), interpolation=cv2.INTER_LINEAR)
|
|
|
|
|
|
mask = np.zeros_like(thickened_nose, dtype=np.float32)
|
|
center_x = new_width // 2
|
|
cv2.circle(mask, (center_x, nh // 2), int(min(new_width, nh) * 0.6), (1, 1, 1), -1, cv2.LINE_AA)
|
|
mask = cv2.GaussianBlur(mask, (21, 21), 10)
|
|
|
|
|
|
left_offset = (new_width - nw) // 2
|
|
|
|
|
|
start_x = max(x + nx - left_offset, 0)
|
|
end_x = min(start_x + new_width, image.shape[1])
|
|
start_y = y + ny
|
|
end_y = start_y + nh
|
|
|
|
|
|
alpha = 0.7
|
|
|
|
|
|
image[start_y:end_y, start_x:end_x] = (
|
|
image[start_y:end_y, start_x:end_x].astype(np.float32) * (1 - mask) +
|
|
thickened_nose[:, :end_x - start_x].astype(np.float32) * mask
|
|
).astype(np.uint8)
|
|
|
|
return image
|
|
|
|
def main():
|
|
st.title("Nose Thickening App")
|
|
|
|
|
|
with st.expander("Application of OpenCV for Nose thickening", expanded=False):
|
|
st.write(
|
|
"The application of OpenCV for nose thickening showcases the power of computer vision in image processing. By leveraging pre-trained classifiers like Haar cascades, the program effectively detects facial features, particularly the nose, within images. The algorithm then applies a thicken effect by resizing the detected nose region, ensuring a realistic blend with the surrounding facial features. This involves techniques such as Gaussian blurring to feather the edges of the modified area, resulting in a seamless transition. The integration with Streamlit allows users to easily upload images, apply the effect, and download the modified results, making sophisticated image manipulation accessible to a broader audience without requiring extensive programming knowledge. This demonstrates OpenCV's versatility in creative applications, from enhancing personal photos to providing entertainment or social media enhancements."
|
|
)
|
|
|
|
|
|
with st.sidebar:
|
|
st.header("Instructions")
|
|
st.write(
|
|
"1) If you choose only one image to upload, the results will be shown on display, and you can click the 'Download Processed Images' button to download the processed images in zip format.\n"
|
|
"2) If you choose more than one image, it will not display any image as results; instead, it will directly show you the 'Download Processed Images' button, and you can click on it to download the processed images in zip format."
|
|
)
|
|
|
|
uploaded_files = st.file_uploader("Upload Images", type=["jpg", "jpeg", "png"], accept_multiple_files=True)
|
|
|
|
if st.button("Thicken Nose"):
|
|
if len(uploaded_files) == 1:
|
|
image = Image.open(uploaded_files[0]).convert("RGB")
|
|
image_np = np.array(image)
|
|
|
|
|
|
output_image = detect_nose_and_realistically_thicken(image_np)
|
|
|
|
|
|
st.image(output_image, caption="Output Image", use_column_width=True)
|
|
|
|
|
|
output_image_rgb = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB)
|
|
|
|
|
|
output_path = 'output_image.jpg'
|
|
cv2.imwrite(output_path, output_image_rgb)
|
|
|
|
st.success("Nose thickening applied! You can download the image below.")
|
|
st.download_button("Download Image", data=open(output_path, "rb").read(), file_name='output_image.jpg', mime='image/jpeg')
|
|
|
|
elif len(uploaded_files) > 1:
|
|
st.warning("Multiple images uploaded. No output will be displayed. Please download the images directly.")
|
|
|
|
|
|
output_dir = 'output_images'
|
|
os.makedirs(output_dir, exist_ok=True)
|
|
|
|
for i, uploaded_file in enumerate(uploaded_files):
|
|
image = Image.open(uploaded_file).convert("RGB")
|
|
image_np = np.array(image)
|
|
output_image = detect_nose_and_realistically_thicken(image_np)
|
|
|
|
|
|
output_image_rgb = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB)
|
|
|
|
output_path = os.path.join(output_dir, f'output_image_{i + 1}.jpg')
|
|
cv2.imwrite(output_path, output_image_rgb)
|
|
|
|
st.success("Nose thickening applied to all images! You can download them below.")
|
|
|
|
|
|
zip_file_path = 'output_images.zip'
|
|
with zipfile.ZipFile(zip_file_path, 'w') as zipf:
|
|
for i in range(len(uploaded_files)):
|
|
zipf.write(os.path.join(output_dir, f'output_image_{i + 1}.jpg'), arcname=f'output_image_{i + 1}.jpg')
|
|
|
|
st.download_button("Download Images", data=open(zip_file_path, "rb").read(), file_name='output_images.zip', mime='application/zip')
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|