В этой статье мы рассмотрим, как создать простой графический интерфейс для наложения фильтров на изображения с использованием языка программирования D и библиотек dlib и QtE5. Основная цель проекта — создать удобный интерфейс, который позволит пользователям легко применять различные фильтры к изображениям и просматривать результаты в режиме реального времени.
Создание нового проекта
Начнем с создания нового проекта. Мы будем использовать пакетный менеджер DUB для управления зависимостями и сборки проекта.
dub init image-filter-gui qt
cd image-filter-gui
Добавление зависимостей и настройка окружения
Для работы с GUI и обработки изображений добавим необходимые зависимости в файл dub.json
:
{
"name": "image-filter-gui",
"dependencies": {
"dlib": "~>0.20.0",
"qte5": "~>5.0.0"
}
}
Создание формы
Теперь создадим форму с двумя элементами для отображения исходного и измененного изображения.
import dlib.image;
import qte5.qtcore;
import qte5.qtgui;
import qte5.qtwidgets;
class ImageFilterApp : QApplication {
QPixmap originalImage;
QPixmap filteredImage;
QLabel originalLabel;
QLabel filteredLabel;
QPushButton applyButton;
QPushButton openButton;
this(int argc, char** argv) {
super(argc, argv);
auto mainWidget = new QWidget();
auto layout = new QVBoxLayout();
mainWidget.setLayout(layout);
originalLabel = new QLabel();
filteredLabel = new QLabel();
openButton = new QPushButton("Open Image");
applyButton = new QPushButton("Apply Filter");
layout.addWidget(originalLabel);
layout.addWidget(filteredLabel);
layout.addWidget(openButton);
layout.addWidget(applyButton);
mainWidget.show();
openButton.clicked.connect(&this.openImage);
applyButton.clicked.connect(&this.applyFilter);
}
void openImage() {
auto fileName = QFileDialog.getOpenFileName(null, "Open Image", "", "Images (*.png *.xpm *.jpg)");
if (!fileName.isEmpty()) {
originalImage = QPixmap(fileName);
originalLabel.setPixmap(originalImage);
}
}
void applyFilter() {
// Logic for applying filter will be added here
}
}
int main(string[] args) {
auto app = new ImageFilterApp(args.length, args.ptr);
return app.exec();
}
Выбор изображения
Для выбора изображения с помощью диалогового окна используем метод QFileDialog.getOpenFileName
.
void openImage() {
auto fileName = QFileDialog.getOpenFileName(null, "Open Image", "", "Images (*.png *.xpm *.jpg)");
if (!fileName.isEmpty()) {
originalImage = QPixmap(fileName);
originalLabel.setPixmap(originalImage);
}
}
Применение фильтра
Для обработки изображения с выбранным фильтром и отображения результата создадим функцию applyFilter
.
void applyFilter() {
// Logic for applying filter
string filterFileName = QFileDialog.getOpenFileName(null, "Open Filter File", "", "Text Files (*.txt)");
if (filterFileName.isEmpty()) return;
string inputImagePath = originalImage.fileName();
string outputImagePath = "filtered_image.png";
runApplyFilters(inputImagePath, filterFileName, outputImagePath);
filteredImage = QPixmap(outputImagePath);
filteredLabel.setPixmap(filteredImage);
}
Действие кнопки «Apply»
Программа получает имя выбранного файла изображения и имя файла с описанием фильтра, затем генерирует имя для нового файла с преобразованным изображением.
void applyFilter() {
string filterFileName = QFileDialog.getOpenFileName(null, "Open Filter File", "", "Text Files (*.txt)");
if (filterFileName.isEmpty()) return;
string inputImagePath = originalImage.fileName();
string outputImagePath = "filtered_image.png";
runApplyFilters(inputImagePath, filterFileName, outputImagePath);
filteredImage = QPixmap(outputImagePath);
filteredLabel.setPixmap(filteredImage);
}
Процесс обработки изображения
Пошагово опишем процесс загрузки исходного изображения, считывания и подготовки фильтра, выполнения свертки изображения с фильтром, сохранения результата в новый файл и отображения его во втором виджете QPictureBox
.
- Загрузка исходного изображения.
- Считывание параметров фильтра из текстового файла.
- Применение фильтра к изображению.
- Сохранение результата в новый файл.
- Отображение результата в виджете
QPictureBox
.
Пример кода для метода runApplyFilters
void runApplyFilters(string inputImagePath, string filterFileName, string outputImagePath) {
auto originalImage = loadImage(inputImagePath);
auto filter = loadFilter(filterFileName);
auto filteredImage = applyConvolutionFilter(originalImage, filter);
saveImage(outputImagePath, filteredImage);
}
Image loadImage(string path) {
// Load image using dlib
return readImage(path);
}
void saveImage(string path, Image img) {
// Save image using dlib
writeImage(path, img);
}
Описание класса для цифрового фильтра
Создадим класс для цифрового фильтра, включая конструктор и методы для получения параметров фильтра.
class Filter {
float[][] kernel;
int size;
this(float[][] kernel) {
this.kernel = kernel;
this.size = kernel.length;
}
int getSize() {
return size;
}
float[][] getKernel() {
return kernel;
}
}
Загрузка фильтра из текстового файла
Метод загрузки фильтра из текстового файла и формат текстового файла с описанием фильтра.
Filter loadFilter(string fileName) {
auto lines = cast(string[]) readText(fileName).splitLines();
auto size = lines.length;
float[][] kernel = new float[][](size, size);
foreach (i, line; lines) {
auto values = line.strip().split(" ");
foreach (j, value; values) {
kernel[i][j] = to!float(value);
}
}
return new Filter(kernel);
}
Пример текстового файла с описанием фильтра:
0 -1 0
-1 5 -1
0 -1 0
Свертка изображения с фильтром
Пример кода для метода свертки изображения с фильтром.
Image applyConvolutionFilter(Image img, Filter filter) {
auto kernel = filter.getKernel();
int size = filter.getSize();
int offset = size / 2;
Image result = img.dup;
foreach (y; 0 .. img.height) {
foreach (x; 0 .. img.width) {
float newValue = 0;
foreach (ky; 0 .. size) {
foreach (kx; 0 .. size) {
int ix = x + kx - offset;
int iy = y + ky - offset;
if (ix >= 0 && iy >= 0 && ix < img.width && iy < img.height) {
newValue += img[iy, ix] * kernel[ky][kx];
}
}
}
result[y, x] = clamp(newValue, 0, 255);
}
}
return result;
}
Пример текстовых файлов с описанием различных фильтров
Пример текстового файла с описанием оператора Лапласа:
0 -1 0
-1 4 -1
0 -1 0
Пример текстового файла с описанием оператора Собеля:
-1 0 1
-2 0 2
-1 0 1
Таким образом, мы создали простой графический интерфейс на языке программирования D с использованием библиотек dlib и QtE5 для наложения фильтров на изображения. Этот проект демонстрирует, как можно сочетать мощные возможности обработки изображений dlib с гибким и удобным интерфейсом, предоставляемым QtE5.
Автор статьи:
Обновлено:
Добавить комментарий