Upload 3 files
Browse files- app.py +131 -0
- haarcascade_frontalface_default.xml +0 -0
- haarcascade_mcs_nose.xml +0 -0
app.py
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
## original color nose thicken
|
2 |
+
import cv2
|
3 |
+
import numpy as np
|
4 |
+
import streamlit as st
|
5 |
+
from PIL import Image
|
6 |
+
import os
|
7 |
+
import zipfile
|
8 |
+
|
9 |
+
def detect_nose_and_realistically_thicken(image):
|
10 |
+
# Load pre-trained classifiers for face and nose detection
|
11 |
+
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
|
12 |
+
nose_cascade = cv2.CascadeClassifier('haarcascade_mcs_nose.xml')
|
13 |
+
|
14 |
+
# Convert the image to grayscale for better detection
|
15 |
+
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
16 |
+
|
17 |
+
# Detect faces in the image
|
18 |
+
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
|
19 |
+
|
20 |
+
for (x, y, w, h) in faces:
|
21 |
+
# For each face, detect the nose
|
22 |
+
face_region = gray[y:y+h, x:x+w]
|
23 |
+
noses = nose_cascade.detectMultiScale(face_region, 1.3, 5)
|
24 |
+
|
25 |
+
for (nx, ny, nw, nh) in noses:
|
26 |
+
# Get the nose region from the original image
|
27 |
+
nose_region = image[y+ny:y+ny+nh, x+nx:x+nx+nw]
|
28 |
+
|
29 |
+
# Thicken the nose by increasing its width symmetrically
|
30 |
+
thicken_factor = 1.5 # Adjust this value to control thickness
|
31 |
+
new_width = int(nw * thicken_factor)
|
32 |
+
|
33 |
+
# Create a thickened nose by resizing
|
34 |
+
thickened_nose = cv2.resize(nose_region, (new_width, nh), interpolation=cv2.INTER_LINEAR)
|
35 |
+
|
36 |
+
# Feather the edges of the thickened nose to blend with the face
|
37 |
+
mask = np.zeros_like(thickened_nose, dtype=np.float32)
|
38 |
+
center_x = new_width // 2
|
39 |
+
cv2.circle(mask, (center_x, nh // 2), int(min(new_width, nh) * 0.6), (1, 1, 1), -1, cv2.LINE_AA)
|
40 |
+
mask = cv2.GaussianBlur(mask, (21, 21), 10) # Feathering
|
41 |
+
|
42 |
+
# Calculate the offsets to center the thickened nose
|
43 |
+
left_offset = (new_width - nw) // 2
|
44 |
+
|
45 |
+
# Ensure not to go out of bounds
|
46 |
+
start_x = max(x + nx - left_offset, 0)
|
47 |
+
end_x = min(start_x + new_width, image.shape[1])
|
48 |
+
start_y = y + ny
|
49 |
+
end_y = start_y + nh
|
50 |
+
|
51 |
+
# Blend the thickened nose smoothly into the face
|
52 |
+
alpha = 0.7 # Controls transparency of thickened nose
|
53 |
+
|
54 |
+
# Blending with the feathered mask to smooth edges
|
55 |
+
image[start_y:end_y, start_x:end_x] = (
|
56 |
+
image[start_y:end_y, start_x:end_x].astype(np.float32) * (1 - mask) +
|
57 |
+
thickened_nose[:, :end_x - start_x].astype(np.float32) * mask
|
58 |
+
).astype(np.uint8)
|
59 |
+
|
60 |
+
return image
|
61 |
+
|
62 |
+
def main():
|
63 |
+
st.title("Nose Thickening App")
|
64 |
+
|
65 |
+
# Modal Popup for Instructions
|
66 |
+
with st.expander("Application of OpenCV for Nose thickening", expanded=False):
|
67 |
+
st.write(
|
68 |
+
"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."
|
69 |
+
)
|
70 |
+
|
71 |
+
# Instructions sidebar
|
72 |
+
with st.sidebar:
|
73 |
+
st.header("Instructions")
|
74 |
+
st.write(
|
75 |
+
"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"
|
76 |
+
"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."
|
77 |
+
)
|
78 |
+
|
79 |
+
uploaded_files = st.file_uploader("Upload Images", type=["jpg", "jpeg", "png"], accept_multiple_files=True)
|
80 |
+
|
81 |
+
if st.button("Thicken Nose"):
|
82 |
+
if len(uploaded_files) == 1:
|
83 |
+
image = Image.open(uploaded_files[0]).convert("RGB")
|
84 |
+
image_np = np.array(image)
|
85 |
+
|
86 |
+
# Apply the nose detection and thickening effect
|
87 |
+
output_image = detect_nose_and_realistically_thicken(image_np)
|
88 |
+
|
89 |
+
# Display the output image
|
90 |
+
st.image(output_image, caption="Output Image", use_column_width=True)
|
91 |
+
|
92 |
+
# Convert the output image to RGB for saving
|
93 |
+
output_image_rgb = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB)
|
94 |
+
|
95 |
+
# Save the output image in the correct color format
|
96 |
+
output_path = 'output_image.jpg'
|
97 |
+
cv2.imwrite(output_path, output_image_rgb) # Save as RGB
|
98 |
+
|
99 |
+
st.success("Nose thickening applied! You can download the image below.")
|
100 |
+
st.download_button("Download Image", data=open(output_path, "rb").read(), file_name='output_image.jpg', mime='image/jpeg')
|
101 |
+
|
102 |
+
elif len(uploaded_files) > 1:
|
103 |
+
st.warning("Multiple images uploaded. No output will be displayed. Please download the images directly.")
|
104 |
+
|
105 |
+
# Save all images in the output directory
|
106 |
+
output_dir = 'output_images'
|
107 |
+
os.makedirs(output_dir, exist_ok=True)
|
108 |
+
|
109 |
+
for i, uploaded_file in enumerate(uploaded_files):
|
110 |
+
image = Image.open(uploaded_file).convert("RGB")
|
111 |
+
image_np = np.array(image)
|
112 |
+
output_image = detect_nose_and_realistically_thicken(image_np)
|
113 |
+
|
114 |
+
# Convert the output image to RGB for saving
|
115 |
+
output_image_rgb = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB)
|
116 |
+
|
117 |
+
output_path = os.path.join(output_dir, f'output_image_{i + 1}.jpg')
|
118 |
+
cv2.imwrite(output_path, output_image_rgb) # Save as RGB
|
119 |
+
|
120 |
+
st.success("Nose thickening applied to all images! You can download them below.")
|
121 |
+
|
122 |
+
# Zip the images for download
|
123 |
+
zip_file_path = 'output_images.zip'
|
124 |
+
with zipfile.ZipFile(zip_file_path, 'w') as zipf:
|
125 |
+
for i in range(len(uploaded_files)):
|
126 |
+
zipf.write(os.path.join(output_dir, f'output_image_{i + 1}.jpg'), arcname=f'output_image_{i + 1}.jpg')
|
127 |
+
|
128 |
+
st.download_button("Download Images", data=open(zip_file_path, "rb").read(), file_name='output_images.zip', mime='application/zip')
|
129 |
+
|
130 |
+
if __name__ == "__main__":
|
131 |
+
main()
|
haarcascade_frontalface_default.xml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
haarcascade_mcs_nose.xml
ADDED
The diff for this file is too large to render.
See raw diff
|
|