Python模块导入报错:视频人脸提取脚本调用失效排查
Let's work through your issues one by one and get your face extraction app up and running properly:
1. Fixing the TypeError: 'module' object is not callable
The first error happens because you're trying to call the entire extractor module like a function (extractor()) in app.py. Modules aren't callable—you need to call specific functions inside the module instead.
2. Why your core logic isn't executing when imported
Your frame extraction and face detection code is wrapped inside the if __name__ == "__main__" block in extractor.py. This block only runs when you run extractor.py directly (e.g., python extractor.py), not when you import it as a module into app.py. We'll fix this by moving the core workflow into a reusable function.
3. Hidden bugs blocking your functionality
There are a few other issues in extractor.py that are stopping the core features from working:
- Path mismatch: Your
extract_framesfunction saves frames to theframes/folder, but your face detection functions are looking for frames indata/—so they can't find any files to process. - Multiprocessing argument error: When passing args to
multiprocessing.Process, you need to pass a tuple.args=(currentFrame_extract)(a list) will cause a parameter mismatch error for yourfind_faces_*functions. - Redundant code: You have four nearly identical
find_faces_*functions—we can simplify this into a single function that takes a starting frame as a parameter. - Useless
formatcall: The.format(i)in yoursaveline is unnecessary (you're already using an f-string withcurrentFrame, andiisn't even used).
Fixed Code
extractor.py
import cv2 import os import face_recognition from PIL import Image import multiprocessing # Create directories once at module load for dir_name in ['frames', 'faces']: try: if not os.path.exists(dir_name): os.makedirs(dir_name) print(f"Created directory: {dir_name}") except OSError as e: print(f'Error creating directory {dir_name}: {e}') def extract_frames(video_file_path): currentFrame_extract = 1 video_capture = cv2.VideoCapture(video_file_path) if not video_capture.isOpened(): print(f"Error: Could not open video file {video_file_path}") return 0 while True: ret, frame = video_capture.read() if not ret: break name = f'frames/frame_{currentFrame_extract}.jpg' print(f"Extracting Frame {currentFrame_extract}, saving as {name}") cv2.imwrite(name, frame) currentFrame_extract += 1 video_capture.release() cv2.destroyAllWindows() return currentFrame_extract - 1 # Return total frames extracted def process_frames(start_frame, total_frames): currentFrame = start_frame while currentFrame <= total_frames: frame_path = f"frames/frame_{currentFrame}.jpg" if not os.path.exists(frame_path): print(f"Warning: Frame {currentFrame} not found, skipping") currentFrame += 4 continue image = face_recognition.load_image_file(frame_path) face_locations = face_recognition.face_locations(image) if face_locations: top, right, bottom, left = face_locations[0] face_image = image[top:bottom, left:right] pil_image = Image.fromarray(face_image) face_save_path = f"faces/face_{currentFrame}.jpg" pil_image.save(face_save_path) print(f"Found face at Frame {currentFrame}, saved to {face_save_path}") currentFrame += 4 def run_face_extraction(video_file_path): total_frames = extract_frames(video_file_path) if total_frames == 0: print("No frames extracted, exiting") return # Create processes with correct tuple arguments processes = [] for start in range(1, 5): p = multiprocessing.Process(target=process_frames, args=(start, total_frames)) processes.append(p) p.start() # Wait for all processes to finish for p in processes: p.join() print("Frame extraction and face detection finished successfully.") # Keep this for direct execution if __name__ == "__main__": run_face_extraction("Video_3.mp4")
app.py
import extractor # Call the exposed function from the module extractor.run_face_extraction("Video_3.mp4") # Replace with your video path if needed
Key Improvements
- Reusable function:
run_face_extractionis now the public entry point that can be called fromapp.py. - Fixed paths: All frame references now use the
frames/directory. - Simplified multiprocessing: Replaced four duplicate functions with a single
process_framesfunction that takes a starting frame parameter. - Error handling: Added checks for video file opening and frame existence to catch issues early.
- Cleaner directory setup: Combined directory creation into a loop to reduce redundancy.
内容的提问来源于stack exchange,提问作者marcr

