Creating a Camera Application using Pyqt5

PyQt5 is one of the most popular GUI libraries available for Python, allowing developers to create desktop applications with ease. In this tutorial, we will walk through the process of creating a camera application using PyQt5. The camera application will allow users to view live camera feed, capture photos, and save them to disk.

What are the advantages of PyQt5?

PyQt5 is a Python binding for the popular cross-platform GUI toolkit, Qt. Here are some key advantages of PyQt5 ?

  • Cross-platform ? PyQt5 applications can run on multiple platforms like Windows, Mac OS X, and Linux.

  • Rich set of widgets ? PyQt5 comes with a comprehensive collection of widgets including buttons, labels, text boxes, tables, and many more for creating complex graphical user interfaces.

  • High performance ? PyQt5 provides high-performance graphical rendering through OpenGL integration, enabling smooth and responsive GUIs.

  • Easy to learn ? Built on top of Python, PyQt5 inherits Python's simplicity and ease of use.

  • Open source ? PyQt5 is free and open-source with an active development community.

Prerequisites

Before starting, ensure you have the following installed ?

  • Python 3.6 or higher

  • A camera connected to your system (built-in or external webcam)

  • An IDE like VS Code, PyCharm, or any text editor

Installing Required Libraries

Install the necessary libraries using pip ?

pip install PyQt5
pip install opencv-python
pip install numpy

Creating the Camera Thread

First, we'll create a separate thread to handle camera operations. This prevents the GUI from freezing while capturing video feed ?

import sys
import cv2
import numpy as np
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QPushButton, QWidget, QFileDialog

class CameraThread(QThread):
    image_signal = pyqtSignal(np.ndarray)

    def __init__(self):
        super().__init__()
        self.capture = None
        self.frame = None
        self.running = False

    def run(self):
        self.capture = cv2.VideoCapture(0)
        self.running = True
        
        while self.running:
            ret, frame = self.capture.read()
            if ret:
                self.frame = frame.copy()
                self.image_signal.emit(frame)
        
        if self.capture:
            self.capture.release()

    def stop(self):
        self.running = False
        self.quit()
        self.wait()

Creating the Main Window

Now we'll create the main application window with camera display and capture functionality ?

class CameraApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt5 Camera Application")
        self.setGeometry(100, 100, 800, 600)
        
        # Create central widget and layout
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)
        
        # Create label for video display
        self.video_label = QLabel()
        self.video_label.setMinimumSize(640, 480)
        self.video_label.setStyleSheet("border: 1px solid black")
        layout.addWidget(self.video_label)
        
        # Create capture button
        self.capture_button = QPushButton("Capture Photo")
        self.capture_button.clicked.connect(self.capture_photo)
        layout.addWidget(self.capture_button)
        
        # Initialize camera thread
        self.camera_thread = CameraThread()
        self.camera_thread.image_signal.connect(self.update_frame)
        self.camera_thread.start()

    def update_frame(self, frame):
        """Update the video display with new frame"""
        rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        h, w, ch = rgb_frame.shape
        bytes_per_line = ch * w
        
        qt_image = QImage(rgb_frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
        scaled_pixmap = QPixmap.fromImage(qt_image).scaled(
            self.video_label.size(), aspectRatioMode=1)
        self.video_label.setPixmap(scaled_pixmap)

    def capture_photo(self):
        """Capture and save current frame"""
        if self.camera_thread.frame is not None:
            filename, _ = QFileDialog.getSaveFileName(
                self, "Save Photo", "photo.jpg", "JPEG files (*.jpg)")
            
            if filename:
                cv2.imwrite(filename, self.camera_thread.frame)
                print(f"Photo saved as {filename}")

    def closeEvent(self, event):
        """Handle application close event"""
        self.camera_thread.stop()
        event.accept()

Complete Application

Here's the complete camera application code ?

import sys
import cv2
import numpy as np
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QPushButton, QWidget, QFileDialog

class CameraThread(QThread):
    image_signal = pyqtSignal(np.ndarray)

    def __init__(self):
        super().__init__()
        self.capture = None
        self.frame = None
        self.running = False

    def run(self):
        self.capture = cv2.VideoCapture(0)
        self.running = True
        
        while self.running:
            ret, frame = self.capture.read()
            if ret:
                self.frame = frame.copy()
                self.image_signal.emit(frame)
        
        if self.capture:
            self.capture.release()

    def stop(self):
        self.running = False
        self.quit()
        self.wait()

class CameraApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt5 Camera Application")
        self.setGeometry(100, 100, 800, 600)
        
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)
        
        self.video_label = QLabel()
        self.video_label.setMinimumSize(640, 480)
        self.video_label.setStyleSheet("border: 1px solid black")
        layout.addWidget(self.video_label)
        
        self.capture_button = QPushButton("Capture Photo")
        self.capture_button.clicked.connect(self.capture_photo)
        layout.addWidget(self.capture_button)
        
        self.camera_thread = CameraThread()
        self.camera_thread.image_signal.connect(self.update_frame)
        self.camera_thread.start()

    def update_frame(self, frame):
        rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        h, w, ch = rgb_frame.shape
        bytes_per_line = ch * w
        
        qt_image = QImage(rgb_frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
        scaled_pixmap = QPixmap.fromImage(qt_image).scaled(
            self.video_label.size(), aspectRatioMode=1)
        self.video_label.setPixmap(scaled_pixmap)

    def capture_photo(self):
        if self.camera_thread.frame is not None:
            filename, _ = QFileDialog.getSaveFileName(
                self, "Save Photo", "photo.jpg", "JPEG files (*.jpg)")
            
            if filename:
                cv2.imwrite(filename, self.camera_thread.frame)
                print(f"Photo saved as {filename}")

    def closeEvent(self, event):
        self.camera_thread.stop()
        event.accept()

def main():
    app = QApplication(sys.argv)
    window = CameraApp()
    window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

Running the Application

To run the application, save the code to a file (e.g., camera_app.py) and execute ?

python camera_app.py

Common Issues and Solutions

  • Camera not detected ? Ensure your camera is properly connected and not being used by another application.

  • Permission denied ? Check system settings to ensure the application has camera access permissions.

  • Import errors ? Verify all required libraries are installed correctly.

  • Black screen ? Try changing the camera index from 0 to 1 in cv2.VideoCapture(0).

Conclusion

This PyQt5 camera application demonstrates how to integrate OpenCV with PyQt5 to create a functional desktop camera app. The application uses threading to handle video capture efficiently while maintaining a responsive GUI. You can extend this basic application by adding features like video recording, filters, or multiple camera support.

Updated on: 2026-03-27T05:57:49+05:30

3K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements