File size: 4,117 Bytes
f468600
1bd58ac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3a66796
1bd58ac
 
 
 
 
3a66796
1bd58ac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3a66796
1bd58ac
 
 
 
 
 
 
 
3a66796
1bd58ac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3a66796
 
 
1bd58ac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3a66796
1bd58ac
3a66796
 
1bd58ac
 
 
d5a59cb
1bd58ac
d5a59cb
 
 
 
 
 
 
 
 
 
 
1bd58ac
d5a59cb
 
1bd58ac
 
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
###
import streamlit as st
import numpy as np
import cv2
import insightface
from insightface.app import FaceAnalysis
import tempfile
import os

# Initialize face analysis and load model
app = FaceAnalysis(name='buffalo_l')
app.prepare(ctx_id=0, det_size=(640, 640))

# Load the face swapper model
swapper = insightface.model_zoo.get_model('inswapper_128.onnx', download=False, download_zip=False)

def swap_faces_in_video(image, video, progress):
    """
    Swaps faces from a source image with faces detected in a video and returns the path to the output video file.
    
    image: Source image (as an array)
    video: Path to the input video file
    progress: Streamlit progress object
    """
    source_faces = app.get(image)

    if len(source_faces) == 0:
        st.error("No face detected in the source image.")
        return None

    source_face = source_faces[0]

    # Create a temporary file to save the output video
    output_path = tempfile.mktemp(suffix='.avi')

    # Open the video file
    cap = cv2.VideoCapture(video)

    # Get video properties for output
    frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fps = cap.get(cv2.CAP_PROP_FPS)

    # Define the codec and create a VideoWriter object
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    out = cv2.VideoWriter(output_path, fourcc, fps, (frame_width, frame_height))

    for i in range(frame_count):
        ret, frame = cap.read()
        if not ret:
            break  # Exit if the video is finished

        # Detect faces in the current frame
        target_faces = app.get(frame)

        # Create a copy of the frame for the result
        result_frame = frame.copy()

        # Swap faces for each detected face in the video frame
        for target_face in target_faces:
            result_frame = swapper.get(result_frame, target_face, source_face, paste_back=True)

        # Write the result frame to the output video
        out.write(result_frame)

        # Update progress bar
        progress.progress((i + 1) / frame_count)

    # Release resources
    cap.release()
    out.release()
    
    return output_path

# Streamlit UI
st.title("Face Swapper in Video")
st.write("Upload an image and a video to swap faces.")

# File uploader for the source image
image_file = st.file_uploader("Upload Source Image", type=["jpg", "jpeg", "png"])

# File uploader for the video
video_file = st.file_uploader("Upload Video", type=["mp4", "avi"])

if st.button("Swap Faces"):
    if image_file is not None and video_file is not None:
        # Read the source image
        source_image = cv2.imdecode(np.frombuffer(image_file.read(), np.uint8), cv2.IMREAD_COLOR)
        
        # Save the uploaded video temporarily
        with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_video:
            tmp_video.write(video_file.read())
            tmp_video_path = tmp_video.name

        # Show a spinner and a progress bar while processing
        with st.spinner("Processing video..."):
            progress_bar = st.progress(0)
            output_video_path = swap_faces_in_video(source_image, tmp_video_path, progress_bar)

        if output_video_path:
            st.success("Face swapping completed!")
            # Play the processed video in Streamlit
            st.video(output_video_path)

            # Provide an option to download the processed video
            with open(output_video_path, "rb") as f:
                st.download_button(
                    label="Download Processed Video",
                    data=f,
                    file_name="output_swapped_video.avi",
                    mime="video/x-msvideo"
                )

            # Clean up temporary files
            os.remove(tmp_video_path)  # Clean up temporary video file
            # Optionally, keep the output video after displaying
            # os.remove(output_video_path)  # Uncomment to delete after displaying
    else:
        st.error("Please upload both an image and a video.")