File size: 6,805 Bytes
1445dfa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
## original color nose thicken
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):
    # Load pre-trained classifiers for face and nose detection
    face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    nose_cascade = cv2.CascadeClassifier('haarcascade_mcs_nose.xml')

    # Convert the image to grayscale for better detection
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Detect faces in the image
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)

    for (x, y, w, h) in faces:
        # For each face, detect the nose
        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:
            # Get the nose region from the original image
            nose_region = image[y+ny:y+ny+nh, x+nx:x+nx+nw]

            # Thicken the nose by increasing its width symmetrically
            thicken_factor = 1.5  # Adjust this value to control thickness
            new_width = int(nw * thicken_factor)

            # Create a thickened nose by resizing
            thickened_nose = cv2.resize(nose_region, (new_width, nh), interpolation=cv2.INTER_LINEAR)

            # Feather the edges of the thickened nose to blend with the face
            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)  # Feathering

            # Calculate the offsets to center the thickened nose
            left_offset = (new_width - nw) // 2

            # Ensure not to go out of bounds
            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

            # Blend the thickened nose smoothly into the face
            alpha = 0.7  # Controls transparency of thickened nose

            # Blending with the feathered mask to smooth edges
            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")

    # Modal Popup for Instructions
    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."
        )

    # Instructions sidebar
    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)

            # Apply the nose detection and thickening effect
            output_image = detect_nose_and_realistically_thicken(image_np)

            # Display the output image
            st.image(output_image, caption="Output Image", use_column_width=True)

            # Convert the output image to RGB for saving
            output_image_rgb = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB)

            # Save the output image in the correct color format
            output_path = 'output_image.jpg'
            cv2.imwrite(output_path, output_image_rgb)  # Save as 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.")

            # Save all images in the output directory
            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)

                # Convert the output image to RGB for saving
                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)  # Save as RGB

            st.success("Nose thickening applied to all images! You can download them below.")

            # Zip the images for download
            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()