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)
project(TV_Denoising_CUDA)
# Find CUDA
enable_language(CUDA)
# Find OpenCV
set(VCPKG_INSTALLED_DIR "E:/programming/vcpkg/installed")
set(OpenCV_DIR "${VCPKG_INSTALLED_DIR}/x64-windows/share/opencv2")
find_package(OpenCV REQUIRED)
# Set CUDA flags and properties
set(CUDA_SEPARABLE_COMPILATION ON)
set(CUDA_PROPAGATE_HOST_FLAGS OFF)
# Add the CUDA source files
file(GLOB CUDA_SOURCE_FILES "src/*.cu")
set_source_files_properties(${CUDA_SOURCE_FILES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
# Add the C++ source files
file(GLOB CPP_SOURCE_FILES "src/*.cpp")
# Set the include directories
include_directories(${OpenCV_DIR} ${CUDA_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})
cmake_minimum_required(VERSION 3.18)
project(TV_Denoising_CUDA)
# Set tool chain
set(VCPKG_DIR "E:/programming/vcpkg")
set(VCPKG_INSTALLED_DIR "${VCPKG_DIR}/installed")
set(CMAKE_TOOLCHAIN_FILE "${VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "Vcpkg toolchain file")
# Find GTK3
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
# Find OpenCV
set(OpenCV_DIR "${VCPKG_INSTALLED_DIR}/x64-windows/share/opencv2")
find_package(OpenCV REQUIRED)
# Find CUDA
enable_language(CUDA)
# Set CUDA flags and properties
set(CUDA_SEPARABLE_COMPILATION ON)
set(CUDA_PROPAGATE_HOST_FLAGS OFF)
# Add the CUDA source files
file(GLOB CUDA_SOURCE_FILES "src/*.cu")
set_source_files_properties(${CUDA_SOURCE_FILES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
# Add the C++ source files
file(GLOB CPP_SOURCE_FILES "src/*.cpp")
# 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
Created: 2023-06-25 10:10:13
Description:
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,
and saves the denoised image to a file.
You can run it with the following command:
./TV_Denoising_CUDA <input_image> <output_image> <lambda> <iterations>
where:
- <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.
- <lambda> is the regularization parameter for TV denoising (optional, default: 0.02).
- <iterations> is the number of iterations for TV denoising (optional, default: 10).
*/
#include <iostream>
#include <opencv2/opencv.hpp>
#include <QApplication>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QSlider>
#include <QFileDialog>
#include <QMessageBox>
#include <QImage>
#include "tv_denoising.hpp"
// Global variables for GUI elements
QLabel* originalImageLabel;
QLabel* resultImageLabel;
QLineEdit* inputImagePathEdit;
QLineEdit* outputImagePathEdit;
QSlider* lambdaSlider;
QSlider* iterationsSlider;
void updateDenoisedImage()
{
std::string inputImagePath = inputImagePathEdit->text().toStdString();
std::string outputImagePath = outputImagePathEdit->text().toStdString();
float lambda = lambdaSlider->value() / 100.0;
int iterations = iterationsSlider->value();
// Read the input image
cv::Mat image = cv::imread(inputImagePath, cv::IMREAD_GRAYSCALE);
// Check if the image was successfully loaded
if (image.empty())
{
QMessageBox::critical(nullptr, "Error", "Failed to read the input image.");
return;
}
// Perform TV denoising
TVDenoising(image, lambda, iterations);
// Display the denoised image
QImage resultImage(image.data, image.cols, image.rows, QImage::Format_Grayscale8);
resultImageLabel->setPixmap(QPixmap::fromImage(resultImage));
// Save the denoised image
cv::imwrite(outputImagePath, image);
}
void openInputImage()
{
QString filePath = QFileDialog::getOpenFileName(nullptr, "Select Input Image");
if (!filePath.isEmpty())
inputImagePathEdit->setText(filePath);
}
void openOutputImage()
{
QString filePath = QFileDialog::getSaveFileName(nullptr, "Select Output Image");
if (!filePath.isEmpty())
outputImagePathEdit->setText(filePath);
}
int main(int argc, char** argv)
{
QApplication app(argc, argv);
// Create the main window
QWidget window;
window.setWindowTitle("TV Image Denoising");
window.resize(800, 600);
// Create the layout
QVBoxLayout* layout = new QVBoxLayout(&window);
// Create the original image label
originalImageLabel = new QLabel("Original Image");
layout->addWidget(originalImageLabel);
// Create the result image label
resultImageLabel = new QLabel("Result Image");
layout->addWidget(resultImageLabel);
// Create the input image path input field
QHBoxLayout* inputLayout = new QHBoxLayout;
QLabel* inputLabel = new QLabel("Input Image:");
inputImagePathEdit = new QLineEdit;
QPushButton* inputBrowseButton = new QPushButton("Browse");
QObject::connect(inputBrowseButton, &QPushButton::clicked, openInputImage);
inputLayout->addWidget(inputLabel);
inputLayout->addWidget(inputImagePathEdit);
inputLayout->addWidget(inputBrowseButton);
layout->addLayout(inputLayout);
// Create the output image path input field
QHBoxLayout* outputLayout = new QHBoxLayout;
QLabel* outputLabel = new QLabel("Output Image:");
outputImagePathEdit = new QLineEdit;
QPushButton* outputBrowseButton = new QPushButton("Browse");
QObject::connect(outputBrowseButton, &QPushButton::clicked, openOutputImage);
outputLayout->addWidget(outputLabel);
outputLayout->addWidget(outputImagePathEdit);
outputLayout->addWidget(outputBrowseButton);
layout->addLayout(outputLayout);
// Create the lambda slider
QLabel* lambdaLabel = new QLabel("Lambda:");
lambdaSlider = new QSlider(Qt::Horizontal);
lambdaSlider->setMinimum(0);
lambdaSlider->setMaximum(100);
layout->addWidget(lambdaLabel);
layout->addWidget(lambdaSlider);
// Create the iterations slider
QLabel* iterationsLabel = new QLabel("Iterations:");
iterationsSlider = new QSlider(Qt::Horizontal);
iterationsSlider->setMinimum(1);
iterationsSlider->setMaximum(100);
layout->addWidget(iterationsLabel);
layout->addWidget(iterationsSlider);
// Create the denoise button
QPushButton* denoiseButton = new QPushButton("Denoise");
QObject::connect(denoiseButton, &QPushButton::clicked, updateDenoisedImage);
layout->addWidget(denoiseButton);
// Show the main window
window.show();
return app.exec();
/*
Author: Vargha Csongor Csaba
Created: 2023-06-25 10:10:13
Description:
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,
and saves the denoised image to a file.
You can run it with the following command:
./TV_Denoising_CUDA <input_image> <output_image> <lambda> <iterations>
where:
- <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.
- <lambda> is the regularization parameter for TV denoising (optional, default: 0.02).
- <iterations> is the number of iterations for TV denoising (optional, default: 10).
*/
#include <iostream>
#include <gtk/gtk.h>
#include <opencv2/opencv.hpp>
#include "tv_denoising.hpp"
// Global variables for GUI elements
GtkLabel* originalImageLabel;
GtkLabel* resultImageLabel;
GtkEntry* inputImagePathEntry;
GtkEntry* outputImagePathEntry;
GtkScale* lambdaScale;
GtkScale* iterationsScale;
static void updateDenoisedImage(GtkWidget* widget, gpointer data)
{
std::string inputImagePath = gtk_entry_get_text(inputImagePathEntry);
std::string outputImagePath = gtk_entry_get_text(outputImagePathEntry);
float lambda = gtk_range_get_value(GTK_RANGE(lambdaScale)) / 100.0;
int iterations = gtk_range_get_value(GTK_RANGE(iterationsScale));
// Read the input image
cv::Mat image = cv::imread(inputImagePath, cv::IMREAD_GRAYSCALE);
// Check if the image was successfully loaded
if (image.empty())
{
GtkWidget* dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
"Failed to read the input image.");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return;
}
// Perform TV denoising
TVDenoising(image, lambda, iterations);
// 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);
gtk_image_set_from_pixbuf(GTK_IMAGE(resultImageLabel), pixbuf);
g_object_unref(pixbuf);
// Save the denoised image
cv::imwrite(outputImagePath, image);
}
static void openInputImage(GtkWidget* widget, gpointer data)
{
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);
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
{
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
gtk_entry_set_text(inputImagePathEntry, filename);
g_free(filename);
}
gtk_widget_destroy(dialog);
}
static void openOutputImage(GtkWidget* widget, gpointer data)
{
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)
{
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
gtk_entry_set_text(outputImagePathEntry, filename);
g_free(filename);
}
gtk_widget_destroy(dialog);
}
int main(int argc, char** argv)
{
// Initialize GTK
gtk_init(&argc, &argv);
// Create the main window
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "TV Image Denoising");
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
// Create the main vertical box layout
GtkWidget* vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add(GTK_CONTAINER(window), vbox);
// Create the original image label
originalImageLabel = GTK_LABEL(gtk_label_new("Original Image"));
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(originalImageLabel), FALSE, FALSE, 0);
// Create the result image label
resultImageLabel = GTK_LABEL(gtk_label_new("Result Image"));
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(resultImageLabel), FALSE, FALSE, 0);
// Create the input image path input field
GtkWidget* inputImageHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start(GTK_BOX(vbox), inputImageHBox, FALSE, FALSE, 0);
GtkWidget* inputImageLabel = gtk_label_new("Input Image:");
gtk_box_pack_start(GTK_BOX(inputImageHBox), inputImageLabel, FALSE, FALSE, 0);
inputImagePathEntry = GTK_ENTRY(gtk_entry_new());
gtk_box_pack_start(GTK_BOX(inputImageHBox), GTK_WIDGET(inputImagePathEntry), TRUE, TRUE, 0);
GtkWidget* inputBrowseButton = gtk_button_new_with_label("Browse");
g_signal_connect(inputBrowseButton, "clicked", G_CALLBACK(openInputImage), window);
gtk_box_pack_start(GTK_BOX(inputImageHBox), inputBrowseButton, FALSE, FALSE, 0);
// Create the output image path input field
GtkWidget* outputImageHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start(GTK_BOX(vbox), outputImageHBox, FALSE, FALSE, 0);
GtkWidget* outputImageLabel = gtk_label_new("Output Image:");
gtk_box_pack_start(GTK_BOX(outputImageHBox), outputImageLabel, FALSE, FALSE, 0);
outputImagePathEntry = GTK_ENTRY(gtk_entry_new());
gtk_box_pack_start(GTK_BOX(outputImageHBox), GTK_WIDGET(outputImagePathEntry), TRUE, TRUE, 0);
GtkWidget* outputBrowseButton = gtk_button_new_with_label("Browse");
g_signal_connect(outputBrowseButton, "clicked", G_CALLBACK(openOutputImage), window);
gtk_box_pack_start(GTK_BOX(outputImageHBox), outputBrowseButton, FALSE, FALSE, 0);
// Create the lambda scale
GtkWidget* lambdaHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start(GTK_BOX(vbox), lambdaHBox, FALSE, FALSE, 0);
GtkWidget* lambdaLabel = gtk_label_new("Lambda:");
gtk_box_pack_start(GTK_BOX(lambdaHBox), lambdaLabel, FALSE, FALSE, 0);
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;
}