Initial commit
This commit is contained in:
137
opencamcpp/CMakeLists.txt
Normal file
137
opencamcpp/CMakeLists.txt
Normal file
@@ -0,0 +1,137 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(opencam LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
# Add OpenCV directory to CMAKE_PREFIX_PATH
|
||||
list(APPEND CMAKE_PREFIX_PATH "/usr/local")
|
||||
|
||||
# Find Qt5
|
||||
find_package(Qt5 COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Widgets
|
||||
Network
|
||||
REQUIRED
|
||||
)
|
||||
|
||||
# Find OpenCV
|
||||
find_package(OpenCV REQUIRED)
|
||||
message(STATUS "OpenCV version: ${OpenCV_VERSION}")
|
||||
message(STATUS "OpenCV libraries: ${OpenCV_LIBS}")
|
||||
message(STATUS "OpenCV include dirs: ${OpenCV_INCLUDE_DIRS}")
|
||||
|
||||
# Check for CUDA support in OpenCV
|
||||
if(";${OpenCV_LIBS};" MATCHES ";opencv_cudaimgproc;")
|
||||
message(STATUS "OpenCV CUDA support found")
|
||||
find_package(CUDA REQUIRED)
|
||||
enable_language(CUDA)
|
||||
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};-O3)
|
||||
add_definitions(-DWITH_CUDA)
|
||||
set(HAS_CUDA TRUE)
|
||||
else()
|
||||
message(STATUS "OpenCV was built without CUDA support. GPU acceleration will be disabled.")
|
||||
set(HAS_CUDA FALSE)
|
||||
endif()
|
||||
|
||||
# Add source files
|
||||
add_executable(${PROJECT_NAME}
|
||||
main.cpp
|
||||
)
|
||||
|
||||
# Link libraries
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Widgets
|
||||
Qt5::Network
|
||||
${OpenCV_LIBS}
|
||||
)
|
||||
|
||||
if(HAS_CUDA)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
${CUDA_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Include directories
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${OpenCV_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(HAS_CUDA)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CUDA_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Installation rules
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION bin
|
||||
COMPONENT applications
|
||||
)
|
||||
|
||||
# Function to safely install a library and its dependencies
|
||||
function(install_library lib_path)
|
||||
if(EXISTS "${lib_path}")
|
||||
file(REAL_PATH "${lib_path}" real_path)
|
||||
install(FILES "${real_path}"
|
||||
DESTINATION lib
|
||||
COMPONENT libraries
|
||||
)
|
||||
|
||||
# Get library dependencies
|
||||
execute_process(
|
||||
COMMAND ldd "${real_path}"
|
||||
OUTPUT_VARIABLE LDD_OUTPUT
|
||||
)
|
||||
|
||||
# Extract and install dependencies
|
||||
string(REGEX MATCHALL "/[^)]*\\.so[^)]*" DEPS "${LDD_OUTPUT}")
|
||||
foreach(dep ${DEPS})
|
||||
if(EXISTS "${dep}" AND NOT "${dep}" MATCHES "^/lib" AND NOT "${dep}" MATCHES "^/usr/lib")
|
||||
install(FILES "${dep}"
|
||||
DESTINATION lib
|
||||
COMPONENT libraries
|
||||
)
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Install OpenCV libraries
|
||||
foreach(lib ${OpenCV_LIBS})
|
||||
get_target_property(lib_location ${lib} LOCATION)
|
||||
if(lib_location)
|
||||
install_library("${lib_location}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Install Qt plugins
|
||||
if(Qt5_DIR)
|
||||
file(GLOB_RECURSE QT_PLUGINS "${Qt5_DIR}/../../../plugins/*.so")
|
||||
foreach(plugin ${QT_PLUGINS})
|
||||
get_filename_component(plugin_path "${plugin}" DIRECTORY)
|
||||
get_filename_component(plugin_dir "${plugin_path}" NAME)
|
||||
install(FILES "${plugin}"
|
||||
DESTINATION plugins/${plugin_dir}
|
||||
COMPONENT plugins
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Print configuration summary
|
||||
message(STATUS "")
|
||||
message(STATUS "Configuration Summary")
|
||||
message(STATUS "--------------------")
|
||||
message(STATUS "OpenCV version: ${OpenCV_VERSION}")
|
||||
message(STATUS "CUDA support: ${HAS_CUDA}")
|
||||
message(STATUS "Qt version: ${Qt5_VERSION}")
|
||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||
message(STATUS "C++ compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
message(STATUS "Installation prefix: ${CMAKE_INSTALL_PREFIX}")
|
||||
message(STATUS "")
|
||||
22
opencamcpp/CMakePresets.json
Normal file
22
opencamcpp/CMakePresets.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"hidden": true,
|
||||
"name": "Qt",
|
||||
"cacheVariables": {
|
||||
"CMAKE_PREFIX_PATH": "$env{QTDIR}"
|
||||
},
|
||||
"vendor": {
|
||||
"qt-project.org/Qt": {
|
||||
"checksum": "wVa86FgEkvdCTVp1/nxvrkaemJc="
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"vendor": {
|
||||
"qt-project.org/Presets": {
|
||||
"checksum": "67SmY24ZeVbebyKD0fGfIzb/bGI="
|
||||
}
|
||||
}
|
||||
}
|
||||
40
opencamcpp/CMakeUserPresets.json
Normal file
40
opencamcpp/CMakeUserPresets.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "Qt-Debug",
|
||||
"inherits": "Qt-Default",
|
||||
"binaryDir": "${sourceDir}/out/build/debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_CXX_FLAGS": "-DQT_QML_DEBUG"
|
||||
},
|
||||
"environment": {
|
||||
"QML_DEBUG_ARGS": "-qmljsdebugger=file:{ff00bfed-29c2-47f8-b4aa-00b2873b1a26},block"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Qt-Release",
|
||||
"inherits": "Qt-Default",
|
||||
"binaryDir": "${sourceDir}/out/build/release",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
},
|
||||
{
|
||||
"hidden": true,
|
||||
"name": "Qt-Default",
|
||||
"inherits": null,
|
||||
"vendor": {
|
||||
"qt-project.org/Default": {
|
||||
"checksum": "VoalogTkyWuFomeO1TLFx0olLJ4="
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"vendor": {
|
||||
"qt-project.org/Presets": {
|
||||
"checksum": "azRZtZDqJVYwlIJYZufPfOYPwkE="
|
||||
}
|
||||
}
|
||||
}
|
||||
90
opencamcpp/build_appimage.sh
Normal file
90
opencamcpp/build_appimage.sh
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Exit on error
|
||||
set -e
|
||||
|
||||
# Function to copy library and its dependencies
|
||||
copy_dependencies() {
|
||||
local binary="$1"
|
||||
local target_dir="$2"
|
||||
|
||||
# Create target directory if it doesn't exist
|
||||
mkdir -p "$target_dir"
|
||||
|
||||
# Get all dependencies
|
||||
ldd "$binary" | while read -r line; do
|
||||
# Extract the library path
|
||||
if [[ $line =~ '=>' ]]; then
|
||||
lib_path=$(echo "$line" | awk '{print $3}')
|
||||
else
|
||||
lib_path=$(echo "$line" | awk '{print $1}')
|
||||
fi
|
||||
|
||||
# Skip system libraries and non-existent files
|
||||
if [[ -f "$lib_path" && ! "$lib_path" =~ ^/lib && ! "$lib_path" =~ ^/usr/lib ]]; then
|
||||
cp -L "$lib_path" "$target_dir/"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Create AppDir structure
|
||||
mkdir -p AppDir/usr/{bin,lib,share/applications,share/icons/hicolor/256x256/apps}
|
||||
|
||||
# Build the application
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release
|
||||
make -j$(nproc)
|
||||
|
||||
# Install to AppDir
|
||||
make DESTDIR=../AppDir install
|
||||
cd ..
|
||||
|
||||
# Copy desktop file and icon
|
||||
cp opencam.desktop AppDir/usr/share/applications/
|
||||
cp icon.png AppDir/usr/share/icons/hicolor/256x256/apps/opencam.png
|
||||
|
||||
# Copy Qt plugins
|
||||
mkdir -p AppDir/usr/plugins
|
||||
for plugin_dir in platforms imageformats xcbglintegrations; do
|
||||
if [ -d "/usr/lib/x86_64-linux-gnu/qt5/plugins/$plugin_dir" ]; then
|
||||
cp -r "/usr/lib/x86_64-linux-gnu/qt5/plugins/$plugin_dir" AppDir/usr/plugins/
|
||||
fi
|
||||
done
|
||||
|
||||
# Copy dependencies for the main executable
|
||||
copy_dependencies "AppDir/usr/bin/opencam" "AppDir/usr/lib"
|
||||
|
||||
# Copy dependencies for Qt plugins
|
||||
find AppDir/usr/plugins -type f -name "*.so" | while read plugin; do
|
||||
copy_dependencies "$plugin" "AppDir/usr/lib"
|
||||
done
|
||||
|
||||
# Create AppRun script
|
||||
cat > AppDir/AppRun << 'EOF'
|
||||
#!/bin/bash
|
||||
HERE="$(dirname "$(readlink -f "${0}")")"
|
||||
export LD_LIBRARY_PATH="${HERE}/usr/lib:${LD_LIBRARY_PATH}"
|
||||
export QT_PLUGIN_PATH="${HERE}/usr/plugins"
|
||||
export QT_QPA_PLATFORM_PLUGIN_PATH="${HERE}/usr/plugins/platforms"
|
||||
exec "${HERE}/usr/bin/opencam" "$@"
|
||||
EOF
|
||||
|
||||
chmod +x AppDir/AppRun
|
||||
|
||||
# Download linuxdeploy if not present
|
||||
if [ ! -f linuxdeploy-x86_64.AppImage ]; then
|
||||
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||
chmod +x linuxdeploy-x86_64.AppImage
|
||||
fi
|
||||
|
||||
if [ ! -f linuxdeploy-plugin-qt-x86_64.AppImage ]; then
|
||||
wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
|
||||
chmod +x linuxdeploy-plugin-qt-x86_64.AppImage
|
||||
fi
|
||||
|
||||
# Create the AppImage
|
||||
export OUTPUT="OpenCam-x86_64.AppImage"
|
||||
./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt --output appimage
|
||||
|
||||
echo "AppImage created successfully: $OUTPUT"
|
||||
83
opencamcpp/build_opencv.sh
Normal file
83
opencamcpp/build_opencv.sh
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Exit on error
|
||||
set -e
|
||||
|
||||
# Function to check CUDA installation
|
||||
check_cuda() {
|
||||
if ! command -v nvcc &> /dev/null; then
|
||||
echo "CUDA not found! Please install CUDA toolkit first."
|
||||
exit 1
|
||||
fi
|
||||
echo "Found CUDA installation: $(nvcc --version | head -n1)"
|
||||
}
|
||||
|
||||
# Function to check GPU
|
||||
check_gpu() {
|
||||
if ! command -v nvidia-smi &> /dev/null; then
|
||||
echo "No NVIDIA GPU found or drivers not installed!"
|
||||
exit 1
|
||||
fi
|
||||
echo "Found GPU: $(nvidia-smi -L)"
|
||||
}
|
||||
|
||||
# Check CUDA and GPU
|
||||
check_cuda
|
||||
check_gpu
|
||||
|
||||
# Get CUDA compute capability
|
||||
CUDA_ARCH=$(nvidia-smi --query-gpu=compute_cap --format=csv,noheader)
|
||||
echo "GPU Compute Capability: $CUDA_ARCH"
|
||||
|
||||
# Create build directory
|
||||
cd ~/opencv_build/opencv
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
# Configure OpenCV build
|
||||
cmake -D CMAKE_BUILD_TYPE=RELEASE \
|
||||
-D CMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \
|
||||
-D WITH_CUDA=ON \
|
||||
-D WITH_CUDNN=OFF \
|
||||
-D OPENCV_DNN_CUDA=ON \
|
||||
-D ENABLE_FAST_MATH=1 \
|
||||
-D CUDA_FAST_MATH=1 \
|
||||
-D CUDA_ARCH_BIN=$CUDA_ARCH \
|
||||
-D WITH_CUBLAS=1 \
|
||||
-D WITH_TBB=ON \
|
||||
-D WITH_V4L=ON \
|
||||
-D WITH_QT=ON \
|
||||
-D WITH_OPENGL=ON \
|
||||
-D WITH_GSTREAMER=ON \
|
||||
-D OPENCV_GENERATE_PKGCONFIG=ON \
|
||||
-D OPENCV_PC_FILE_NAME=opencv.pc \
|
||||
-D OPENCV_ENABLE_NONFREE=ON \
|
||||
-D INSTALL_PYTHON_EXAMPLES=OFF \
|
||||
-D INSTALL_C_EXAMPLES=OFF \
|
||||
-D BUILD_EXAMPLES=OFF \
|
||||
-D BUILD_opencv_cudacodec=OFF \
|
||||
-D OPENCV_ENABLE_MEMALIGN=ON \
|
||||
-D WITH_OPENEXR=ON \
|
||||
-D OPENCV_ENABLE_MEMALIGN=ON \
|
||||
-D WITH_EIGEN=ON \
|
||||
-D ENABLE_PRECOMPILED_HEADERS=OFF \
|
||||
..
|
||||
|
||||
# Build using all available CPU cores
|
||||
make -j$(nproc)
|
||||
|
||||
# Install
|
||||
sudo make install
|
||||
sudo ldconfig
|
||||
|
||||
# Print OpenCV installation information
|
||||
echo "OpenCV installation completed!"
|
||||
echo "OpenCV version: $(pkg-config --modversion opencv4)"
|
||||
echo "Installation location: $(pkg-config --variable=prefix opencv4)"
|
||||
|
||||
# Create a pkg-config path file
|
||||
sudo sh -c 'echo "/usr/local/lib/pkgconfig" > /etc/ld.so.conf.d/opencv.conf'
|
||||
sudo ldconfig
|
||||
|
||||
echo "Setup complete! You can now use OpenCV with CUDA support."
|
||||
BIN
opencamcpp/icon.png
Normal file
BIN
opencamcpp/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
7
opencamcpp/icon.svg
Normal file
7
opencamcpp/icon.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
|
||||
<circle cx="128" cy="128" r="120" fill="#2196F3"/>
|
||||
<circle cx="128" cy="128" r="90" fill="#1976D2"/>
|
||||
<circle cx="128" cy="128" r="45" fill="#FFFFFF"/>
|
||||
<circle cx="128" cy="128" r="25" fill="#1976D2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 359 B |
311
opencamcpp/main.cpp
Normal file
311
opencamcpp/main.cpp
Normal file
@@ -0,0 +1,311 @@
|
||||
#include <opencv2/opencv.hpp>
|
||||
#ifdef WITH_CUDA
|
||||
#include <opencv2/cudaimgproc.hpp>
|
||||
#include <opencv2/cudawarping.hpp>
|
||||
#include <opencv2/cudaobjdetect.hpp>
|
||||
#include <opencv2/cudabgsegm.hpp>
|
||||
#include <opencv2/cudacodec.hpp>
|
||||
#include <opencv2/core/cuda.hpp>
|
||||
#endif
|
||||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QComboBox>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressDialog>
|
||||
#include <QTimer>
|
||||
#include <QThread>
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <QProgressBar>
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
class FrameProcessor : public QThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FrameProcessor(QObject* parent = nullptr) : QThread(parent), running(false) {
|
||||
#ifdef WITH_CUDA
|
||||
// Initialize CUDA device
|
||||
cv::cuda::setDevice(0);
|
||||
stream = cv::cuda::Stream();
|
||||
#endif
|
||||
}
|
||||
|
||||
void startProcessing() {
|
||||
running = true;
|
||||
if (!isRunning()) start();
|
||||
}
|
||||
|
||||
void stopProcessing() {
|
||||
running = false;
|
||||
wait();
|
||||
}
|
||||
|
||||
void setNet(cv::dnn::Net& net) {
|
||||
std::lock_guard<std::mutex> lock(netMutex);
|
||||
this->net = net;
|
||||
}
|
||||
|
||||
void queueFrame(const cv::Mat& frame) {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
frameQueue.push(frame);
|
||||
condition.notify_one();
|
||||
}
|
||||
|
||||
signals:
|
||||
void frameProcessed(QImage image);
|
||||
|
||||
protected:
|
||||
void run() override {
|
||||
while (running) {
|
||||
cv::Mat frame;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(queueMutex);
|
||||
condition.wait(lock, [this] { return !frameQueue.empty() || !running; });
|
||||
if (!running) break;
|
||||
frame = frameQueue.front();
|
||||
frameQueue.pop();
|
||||
}
|
||||
|
||||
if (frame.empty()) continue;
|
||||
|
||||
#ifdef WITH_CUDA
|
||||
// GPU processing path
|
||||
cv::cuda::GpuMat gpuFrame;
|
||||
gpuFrame.upload(frame, stream);
|
||||
|
||||
cv::cuda::GpuMat gpuResized;
|
||||
cv::cuda::resize(gpuFrame, gpuResized, cv::Size(416, 416), 0, 0, cv::INTER_CUBIC, stream);
|
||||
|
||||
// Download for DNN processing (until we implement CUDA DNN)
|
||||
cv::Mat resized;
|
||||
gpuResized.download(resized, stream);
|
||||
#else
|
||||
// CPU processing path
|
||||
cv::Mat resized;
|
||||
cv::resize(frame, resized, cv::Size(416, 416), 0, 0, cv::INTER_CUBIC);
|
||||
#endif
|
||||
|
||||
// Object detection
|
||||
cv::Mat blob;
|
||||
cv::dnn::blobFromImage(resized, blob, 1/255.0, cv::Size(416, 416), cv::Scalar(0,0,0), true, false);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(netMutex);
|
||||
net.setInput(blob);
|
||||
std::vector<cv::Mat> outs;
|
||||
net.forward(outs, net.getUnconnectedOutLayersNames());
|
||||
|
||||
std::vector<int> classIds;
|
||||
std::vector<float> confidences;
|
||||
std::vector<cv::Rect> boxes;
|
||||
|
||||
for (const auto& out : outs) {
|
||||
float* data = (float*)out.data;
|
||||
for (int j = 0; j < out.rows; ++j, data += out.cols) {
|
||||
cv::Mat scores = out.row(j).colRange(5, out.cols);
|
||||
cv::Point classIdPoint;
|
||||
double confidence;
|
||||
cv::minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
|
||||
|
||||
if (confidence > 0.5) {
|
||||
int centerX = (int)(data[0] * frame.cols);
|
||||
int centerY = (int)(data[1] * frame.rows);
|
||||
int width = (int)(data[2] * frame.cols);
|
||||
int height = (int)(data[3] * frame.rows);
|
||||
int left = centerX - width / 2;
|
||||
int top = centerY - height / 2;
|
||||
|
||||
classIds.push_back(classIdPoint.x);
|
||||
confidences.push_back((float)confidence);
|
||||
boxes.push_back(cv::Rect(left, top, width, height));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> indices;
|
||||
cv::dnn::NMSBoxes(boxes, confidences, 0.5, 0.4, indices);
|
||||
|
||||
for (size_t i = 0; i < indices.size(); ++i) {
|
||||
int idx = indices[i];
|
||||
cv::Rect box = boxes[idx];
|
||||
cv::rectangle(frame, box, cv::Scalar(0, 255, 0), 2);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_CUDA
|
||||
// Convert to RGB on GPU
|
||||
cv::cuda::GpuMat gpuRGB;
|
||||
cv::cuda::cvtColor(gpuFrame, gpuRGB, cv::COLOR_BGR2RGB, 0, stream);
|
||||
cv::Mat rgb;
|
||||
gpuRGB.download(rgb, stream);
|
||||
#else
|
||||
// Convert to RGB on CPU
|
||||
cv::Mat rgb;
|
||||
cv::cvtColor(frame, rgb, cv::COLOR_BGR2RGB);
|
||||
#endif
|
||||
|
||||
// Convert to QImage
|
||||
QImage qimg(rgb.data, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888);
|
||||
emit frameProcessed(qimg.copy());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<bool> running;
|
||||
#ifdef WITH_CUDA
|
||||
cv::cuda::Stream stream;
|
||||
#endif
|
||||
cv::dnn::Net net;
|
||||
std::queue<cv::Mat> frameQueue;
|
||||
std::mutex queueMutex;
|
||||
std::mutex netMutex;
|
||||
std::condition_variable condition;
|
||||
};
|
||||
|
||||
class CameraApp : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CameraApp(QWidget* parent = nullptr) : QMainWindow(parent) {
|
||||
setWindowTitle("GPU-Accelerated Object Detection");
|
||||
setGeometry(100, 100, 1280, 720);
|
||||
|
||||
#ifdef WITH_CUDA
|
||||
// Check CUDA device
|
||||
int deviceCount = cv::cuda::getCudaEnabledDeviceCount();
|
||||
if (deviceCount == 0) {
|
||||
QMessageBox::warning(this, "Warning", "No CUDA capable devices found. Falling back to CPU processing.");
|
||||
} else {
|
||||
cv::cuda::printCudaDeviceInfo(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
setupUI();
|
||||
initializeObjectDetection();
|
||||
processor = new FrameProcessor(this);
|
||||
connect(processor, &FrameProcessor::frameProcessed, this, &CameraApp::updateFrame);
|
||||
}
|
||||
|
||||
~CameraApp() {
|
||||
stopCamera();
|
||||
if (processor) {
|
||||
processor->stopProcessing();
|
||||
delete processor;
|
||||
}
|
||||
}
|
||||
|
||||
private slots:
|
||||
void startCamera() {
|
||||
if (!cap.isOpened()) {
|
||||
cap.open(currentCamera);
|
||||
cap.set(cv::CAP_PROP_FRAME_WIDTH, 1920);
|
||||
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 1080);
|
||||
cap.set(cv::CAP_PROP_FPS, 120); // Request maximum FPS
|
||||
|
||||
#ifdef WITH_CUDA
|
||||
// Try to use CUDA video decoder if available
|
||||
cap.set(cv::CAP_PROP_CUDA_DEVICE, 0);
|
||||
#endif
|
||||
|
||||
if (!cap.isOpened()) {
|
||||
QMessageBox::critical(this, "Error", "Failed to open camera!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
processor->startProcessing();
|
||||
timer->start(0); // Run as fast as possible
|
||||
}
|
||||
|
||||
void stopCamera() {
|
||||
timer->stop();
|
||||
processor->stopProcessing();
|
||||
if (cap.isOpened()) {
|
||||
cap.release();
|
||||
}
|
||||
}
|
||||
|
||||
void captureFrame() {
|
||||
if (!cap.isOpened()) return;
|
||||
|
||||
cv::Mat frame;
|
||||
cap >> frame;
|
||||
if (frame.empty()) return;
|
||||
|
||||
processor->queueFrame(frame);
|
||||
}
|
||||
|
||||
void updateFrame(const QImage& image) {
|
||||
QPixmap pixmap = QPixmap::fromImage(image);
|
||||
videoLabel->setPixmap(pixmap.scaled(videoLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
|
||||
private:
|
||||
void setupUI() {
|
||||
QWidget* centralWidget = new QWidget(this);
|
||||
setCentralWidget(centralWidget);
|
||||
QVBoxLayout* layout = new QVBoxLayout(centralWidget);
|
||||
|
||||
videoLabel = new QLabel(this);
|
||||
videoLabel->setMinimumSize(640, 480);
|
||||
layout->addWidget(videoLabel);
|
||||
|
||||
cameraSelect = new QComboBox(this);
|
||||
detectCameras();
|
||||
layout->addWidget(cameraSelect);
|
||||
|
||||
startButton = new QPushButton("Start Camera", this);
|
||||
connect(startButton, &QPushButton::clicked, this, &CameraApp::startCamera);
|
||||
layout->addWidget(startButton);
|
||||
|
||||
stopButton = new QPushButton("Stop Camera", this);
|
||||
connect(stopButton, &QPushButton::clicked, this, &CameraApp::stopCamera);
|
||||
layout->addWidget(stopButton);
|
||||
|
||||
timer = new QTimer(this);
|
||||
connect(timer, &QTimer::timeout, this, &CameraApp::captureFrame);
|
||||
}
|
||||
|
||||
void detectCameras() {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
cv::VideoCapture temp(i);
|
||||
if (temp.isOpened()) {
|
||||
cameraSelect->addItem("Camera " + QString::number(i), i);
|
||||
temp.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initializeObjectDetection() {
|
||||
// Download and load YOLO model (implementation similar to Python version)
|
||||
// ...
|
||||
}
|
||||
|
||||
QLabel* videoLabel;
|
||||
QComboBox* cameraSelect;
|
||||
QPushButton* startButton;
|
||||
QPushButton* stopButton;
|
||||
QTimer* timer;
|
||||
cv::VideoCapture cap;
|
||||
int currentCamera = 0;
|
||||
FrameProcessor* processor;
|
||||
};
|
||||
|
||||
#include "main.moc"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
CameraApp window;
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
||||
10
opencamcpp/opencam.desktop
Normal file
10
opencamcpp/opencam.desktop
Normal file
@@ -0,0 +1,10 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=OpenCam
|
||||
Comment=Real-time object detection using OpenCV and YOLO
|
||||
Exec=opencam
|
||||
Icon=opencam
|
||||
Categories=Graphics;Video;
|
||||
Keywords=camera;detection;opencv;yolo;
|
||||
Terminal=false
|
||||
StartupNotify=true
|
||||
Reference in New Issue
Block a user