Compare commits

...

3 Commits

Author SHA1 Message Date
82b6094c1e Switch qt to gtk 2023-06-25 18:15:25 +02:00
7c2cd2fff0 Implement updateDenoisedImage(), call TVdenoising 2023-06-25 16:07:35 +02:00
8b1bec6fa5 Add QT widgets 2023-06-25 16:07:05 +02:00
2 changed files with 216 additions and 91 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,61 +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 "tv_denoising.hpp"
int main(int argc, char** argv)
{
// Check if the required arguments are provided
if (argc < 3)
{
std::cerr << "Usage: ./TV_Denoising_CUDA <input_image> <output_image> [<lambda>] [<iterations>]" << std::endl;
return 1;
}
// Read the input arguments
std::string inputImagePath = argv[1];
std::string outputImagePath = argv[2];
float lambda = 0.02;
int iterations = 10;
// Check if optional arguments are provided and update the corresponding variables
if (argc >= 4)
lambda = std::stof(argv[3]);
if (argc >= 5)
iterations = std::stoi(argv[4]);
// Read the input image
cv::Mat image = cv::imread(inputImagePath, cv::IMREAD_GRAYSCALE);
// Check if the image was successfully loaded
if (image.empty())
{
std::cerr << "Failed to read the input image." << std::endl;
return 1;
}
// Perform TV denoising
TVDenoising(image, lambda, iterations);
// Display and save the denoised image
cv::imshow("Denoised Image", image);
cv::waitKey(0);
cv::imwrite(outputImagePath, image);
return 0;
}
/*
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;
}