Switch qt to gtk

This commit is contained in:
2023-06-25 18:15:25 +02:00
parent 7c2cd2fff0
commit 82b6094c1e
2 changed files with 215 additions and 177 deletions

View File

@@ -1,30 +1,40 @@
cmake_minimum_required(VERSION 3.18) cmake_minimum_required(VERSION 3.18)
project(TV_Denoising_CUDA) project(TV_Denoising_CUDA)
# Find CUDA # Set tool chain
enable_language(CUDA) set(VCPKG_DIR "E:/programming/vcpkg")
set(VCPKG_INSTALLED_DIR "${VCPKG_DIR}/installed")
# Find OpenCV set(CMAKE_TOOLCHAIN_FILE "${VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "Vcpkg toolchain file")
set(VCPKG_INSTALLED_DIR "E:/programming/vcpkg/installed")
set(OpenCV_DIR "${VCPKG_INSTALLED_DIR}/x64-windows/share/opencv2") # Find GTK3
find_package(OpenCV REQUIRED) find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
# Set CUDA flags and properties
set(CUDA_SEPARABLE_COMPILATION ON) # Find OpenCV
set(CUDA_PROPAGATE_HOST_FLAGS OFF) set(OpenCV_DIR "${VCPKG_INSTALLED_DIR}/x64-windows/share/opencv2")
find_package(OpenCV REQUIRED)
# Add the CUDA source files
file(GLOB CUDA_SOURCE_FILES "src/*.cu") # Find CUDA
set_source_files_properties(${CUDA_SOURCE_FILES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ) enable_language(CUDA)
# Add the C++ source files # Set CUDA flags and properties
file(GLOB CPP_SOURCE_FILES "src/*.cpp") set(CUDA_SEPARABLE_COMPILATION ON)
set(CUDA_PROPAGATE_HOST_FLAGS OFF)
# Set the include directories
include_directories(${OpenCV_DIR} ${CUDA_INCLUDE_DIRS} "include") # Add the CUDA source files
file(GLOB CUDA_SOURCE_FILES "src/*.cu")
# Create the executable set_source_files_properties(${CUDA_SOURCE_FILES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
add_executable(TV_Denoising_CUDA ${CPP_SOURCE_FILES} ${CUDA_SOURCE_FILES})
# Add the C++ source files
# Link CUDA libraries file(GLOB CPP_SOURCE_FILES "src/*.cpp")
target_link_libraries(TV_Denoising_CUDA ${CUDA_LIBRARIES})
# Set the include directories
include_directories(${OpenCV_DIR} ${CUDA_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} "include")
# Create the executable
add_executable(TV_Denoising_CUDA ${CPP_SOURCE_FILES} ${CUDA_SOURCE_FILES})
# Link CUDA libraries
target_link_libraries(TV_Denoising_CUDA ${CUDA_LIBRARIES} ${GTK3_LIBRARIES})
target_compile_options(TV_Denoising_CUDA PUBLIC ${GTK3_CFLAGS_OTHER})

View File

@@ -1,148 +1,176 @@
/* /*
Author: Vargha Csongor Csaba Author: Vargha Csongor Csaba
Created: 2023-06-25 10:10:13 Created: 2023-06-25 10:10:13
Description: Description:
This file contains the main function for the TV image denoising cli tool. This file contains the main function for the TV image denoising cli tool.
It reads an image file, denoises it using the TV denoising algorithm, It reads an image file, denoises it using the TV denoising algorithm,
and saves the denoised image to a file. and saves the denoised image to a file.
You can run it with the following command: You can run it with the following command:
./TV_Denoising_CUDA <input_image> <output_image> <lambda> <iterations> ./TV_Denoising_CUDA <input_image> <output_image> <lambda> <iterations>
where: where:
- <input_image> is the path to the input image file you want to denoise. - <input_image> is the path to the input image file you want to denoise.
- <output_image> is the path to the output denoised image file. - <output_image> is the path to the output denoised image file.
- <lambda> is the regularization parameter for TV denoising (optional, default: 0.02). - <lambda> is the regularization parameter for TV denoising (optional, default: 0.02).
- <iterations> is the number of iterations for TV denoising (optional, default: 10). - <iterations> is the number of iterations for TV denoising (optional, default: 10).
*/ */
#include <iostream> #include <iostream>
#include <opencv2/opencv.hpp> #include <gtk/gtk.h>
#include <QApplication> #include <opencv2/opencv.hpp>
#include <QVBoxLayout> #include "tv_denoising.hpp"
#include <QHBoxLayout>
#include <QLabel> // Global variables for GUI elements
#include <QLineEdit> GtkLabel* originalImageLabel;
#include <QPushButton> GtkLabel* resultImageLabel;
#include <QSlider> GtkEntry* inputImagePathEntry;
#include <QFileDialog> GtkEntry* outputImagePathEntry;
#include <QMessageBox> GtkScale* lambdaScale;
#include <QImage> GtkScale* iterationsScale;
#include "tv_denoising.hpp"
static void updateDenoisedImage(GtkWidget* widget, gpointer data)
// Global variables for GUI elements {
QLabel* originalImageLabel; std::string inputImagePath = gtk_entry_get_text(inputImagePathEntry);
QLabel* resultImageLabel; std::string outputImagePath = gtk_entry_get_text(outputImagePathEntry);
QLineEdit* inputImagePathEdit; float lambda = gtk_range_get_value(GTK_RANGE(lambdaScale)) / 100.0;
QLineEdit* outputImagePathEdit; int iterations = gtk_range_get_value(GTK_RANGE(iterationsScale));
QSlider* lambdaSlider;
QSlider* iterationsSlider; // Read the input image
cv::Mat image = cv::imread(inputImagePath, cv::IMREAD_GRAYSCALE);
void updateDenoisedImage()
{ // Check if the image was successfully loaded
std::string inputImagePath = inputImagePathEdit->text().toStdString(); if (image.empty())
std::string outputImagePath = outputImagePathEdit->text().toStdString(); {
float lambda = lambdaSlider->value() / 100.0; GtkWidget* dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
int iterations = iterationsSlider->value(); "Failed to read the input image.");
gtk_dialog_run(GTK_DIALOG(dialog));
// Read the input image gtk_widget_destroy(dialog);
cv::Mat image = cv::imread(inputImagePath, cv::IMREAD_GRAYSCALE); return;
}
// Check if the image was successfully loaded
if (image.empty()) // Perform TV denoising
{ TVDenoising(image, lambda, iterations);
QMessageBox::critical(nullptr, "Error", "Failed to read the input image.");
return; // Display the denoised image
} GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(image.data, GDK_COLORSPACE_RGB, FALSE, 8, image.cols, image.rows,
image.step, NULL, NULL);
// Perform TV denoising gtk_image_set_from_pixbuf(GTK_IMAGE(resultImageLabel), pixbuf);
TVDenoising(image, lambda, iterations); g_object_unref(pixbuf);
// Display the denoised image // Save the denoised image
QImage resultImage(image.data, image.cols, image.rows, QImage::Format_Grayscale8); cv::imwrite(outputImagePath, image);
resultImageLabel->setPixmap(QPixmap::fromImage(resultImage)); }
// Save the denoised image static void openInputImage(GtkWidget* widget, gpointer data)
cv::imwrite(outputImagePath, image); {
} GtkWidget* dialog = gtk_file_chooser_dialog_new("Select Input Image", GTK_WINDOW(data), GTK_FILE_CHOOSER_ACTION_OPEN,
"Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL);
void openInputImage() if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
{ {
QString filePath = QFileDialog::getOpenFileName(nullptr, "Select Input Image"); char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
if (!filePath.isEmpty()) gtk_entry_set_text(inputImagePathEntry, filename);
inputImagePathEdit->setText(filePath); g_free(filename);
} }
gtk_widget_destroy(dialog);
void openOutputImage() }
{
QString filePath = QFileDialog::getSaveFileName(nullptr, "Select Output Image"); static void openOutputImage(GtkWidget* widget, gpointer data)
if (!filePath.isEmpty()) {
outputImagePathEdit->setText(filePath); GtkWidget* dialog = gtk_file_chooser_dialog_new("Select Output Image", GTK_WINDOW(data), GTK_FILE_CHOOSER_ACTION_SAVE,
} "Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL);
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
int main(int argc, char** argv) {
{ char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
QApplication app(argc, argv); gtk_entry_set_text(outputImagePathEntry, filename);
g_free(filename);
// Create the main window }
QWidget window; gtk_widget_destroy(dialog);
window.setWindowTitle("TV Image Denoising"); }
window.resize(800, 600);
int main(int argc, char** argv)
// Create the layout {
QVBoxLayout* layout = new QVBoxLayout(&window); // Initialize GTK
gtk_init(&argc, &argv);
// Create the original image label
originalImageLabel = new QLabel("Original Image"); // Create the main window
layout->addWidget(originalImageLabel); GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "TV Image Denoising");
// Create the result image label gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
resultImageLabel = new QLabel("Result Image"); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
layout->addWidget(resultImageLabel);
// Create the main vertical box layout
// Create the input image path input field GtkWidget* vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
QHBoxLayout* inputLayout = new QHBoxLayout; gtk_container_add(GTK_CONTAINER(window), vbox);
QLabel* inputLabel = new QLabel("Input Image:");
inputImagePathEdit = new QLineEdit; // Create the original image label
QPushButton* inputBrowseButton = new QPushButton("Browse"); originalImageLabel = GTK_LABEL(gtk_label_new("Original Image"));
QObject::connect(inputBrowseButton, &QPushButton::clicked, openInputImage); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(originalImageLabel), FALSE, FALSE, 0);
inputLayout->addWidget(inputLabel);
inputLayout->addWidget(inputImagePathEdit); // Create the result image label
inputLayout->addWidget(inputBrowseButton); resultImageLabel = GTK_LABEL(gtk_label_new("Result Image"));
layout->addLayout(inputLayout); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(resultImageLabel), FALSE, FALSE, 0);
// Create the output image path input field // Create the input image path input field
QHBoxLayout* outputLayout = new QHBoxLayout; GtkWidget* inputImageHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
QLabel* outputLabel = new QLabel("Output Image:"); gtk_box_pack_start(GTK_BOX(vbox), inputImageHBox, FALSE, FALSE, 0);
outputImagePathEdit = new QLineEdit;
QPushButton* outputBrowseButton = new QPushButton("Browse"); GtkWidget* inputImageLabel = gtk_label_new("Input Image:");
QObject::connect(outputBrowseButton, &QPushButton::clicked, openOutputImage); gtk_box_pack_start(GTK_BOX(inputImageHBox), inputImageLabel, FALSE, FALSE, 0);
outputLayout->addWidget(outputLabel);
outputLayout->addWidget(outputImagePathEdit); inputImagePathEntry = GTK_ENTRY(gtk_entry_new());
outputLayout->addWidget(outputBrowseButton); gtk_box_pack_start(GTK_BOX(inputImageHBox), GTK_WIDGET(inputImagePathEntry), TRUE, TRUE, 0);
layout->addLayout(outputLayout);
GtkWidget* inputBrowseButton = gtk_button_new_with_label("Browse");
// Create the lambda slider g_signal_connect(inputBrowseButton, "clicked", G_CALLBACK(openInputImage), window);
QLabel* lambdaLabel = new QLabel("Lambda:"); gtk_box_pack_start(GTK_BOX(inputImageHBox), inputBrowseButton, FALSE, FALSE, 0);
lambdaSlider = new QSlider(Qt::Horizontal);
lambdaSlider->setMinimum(0); // Create the output image path input field
lambdaSlider->setMaximum(100); GtkWidget* outputImageHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
layout->addWidget(lambdaLabel); gtk_box_pack_start(GTK_BOX(vbox), outputImageHBox, FALSE, FALSE, 0);
layout->addWidget(lambdaSlider);
GtkWidget* outputImageLabel = gtk_label_new("Output Image:");
// Create the iterations slider gtk_box_pack_start(GTK_BOX(outputImageHBox), outputImageLabel, FALSE, FALSE, 0);
QLabel* iterationsLabel = new QLabel("Iterations:");
iterationsSlider = new QSlider(Qt::Horizontal); outputImagePathEntry = GTK_ENTRY(gtk_entry_new());
iterationsSlider->setMinimum(1); gtk_box_pack_start(GTK_BOX(outputImageHBox), GTK_WIDGET(outputImagePathEntry), TRUE, TRUE, 0);
iterationsSlider->setMaximum(100);
layout->addWidget(iterationsLabel); GtkWidget* outputBrowseButton = gtk_button_new_with_label("Browse");
layout->addWidget(iterationsSlider); g_signal_connect(outputBrowseButton, "clicked", G_CALLBACK(openOutputImage), window);
gtk_box_pack_start(GTK_BOX(outputImageHBox), outputBrowseButton, FALSE, FALSE, 0);
// Create the denoise button
QPushButton* denoiseButton = new QPushButton("Denoise"); // Create the lambda scale
QObject::connect(denoiseButton, &QPushButton::clicked, updateDenoisedImage); GtkWidget* lambdaHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
layout->addWidget(denoiseButton); gtk_box_pack_start(GTK_BOX(vbox), lambdaHBox, FALSE, FALSE, 0);
// Show the main window GtkWidget* lambdaLabel = gtk_label_new("Lambda:");
window.show(); gtk_box_pack_start(GTK_BOX(lambdaHBox), lambdaLabel, FALSE, FALSE, 0);
return app.exec(); lambdaScale = GTK_SCALE(gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 100, 1));
gtk_scale_set_value_pos(lambdaScale, GTK_POS_RIGHT);
gtk_scale_set_digits(lambdaScale, 2);
gtk_box_pack_start(GTK_BOX(lambdaHBox), GTK_WIDGET(lambdaScale), TRUE, TRUE, 0);
// Create the iterations scale
GtkWidget* iterationsHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start(GTK_BOX(vbox), iterationsHBox, FALSE, FALSE, 0);
GtkWidget* iterationsLabel = gtk_label_new("Iterations:");
gtk_box_pack_start(GTK_BOX(iterationsHBox), iterationsLabel, FALSE, FALSE, 0);
iterationsScale = GTK_SCALE(gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 1, 100, 1));
gtk_scale_set_value_pos(iterationsScale, GTK_POS_RIGHT);
gtk_scale_set_digits(iterationsScale, 0);
gtk_box_pack_start(GTK_BOX(iterationsHBox), GTK_WIDGET(iterationsScale), TRUE, TRUE, 0);
// Create the denoise button
GtkWidget* denoiseButton = gtk_button_new_with_label("Denoise");
g_signal_connect(denoiseButton, "clicked", G_CALLBACK(updateDenoisedImage), NULL);
gtk_box_pack_start(GTK_BOX(vbox), denoiseButton, FALSE, FALSE, 0);
// Show all widgets
gtk_widget_show_all(window);
// Run the GTK main loop
gtk_main();
return 0;
} }