-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 18d5b88
Showing
8 changed files
with
589 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
*.o | ||
*.jpg | ||
*.png | ||
*.bmp | ||
*.user | ||
build/ | ||
ui_interface.h | ||
moc_interface.cpp | ||
Basic_image_processing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#------------------------------------------------- | ||
# | ||
# Project created by QtCreator 2019-02-08T15:58:23 | ||
# | ||
#------------------------------------------------- | ||
|
||
QT += core gui | ||
|
||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets | ||
|
||
TARGET = Basic_image_processing | ||
TEMPLATE = app | ||
|
||
# The following define makes your compiler emit warnings if you use | ||
# any feature of Qt which has been marked as deprecated (the exact warnings | ||
# depend on your compiler). Please consult the documentation of the | ||
# deprecated API in order to know how to port your code away from it. | ||
DEFINES += QT_DEPRECATED_WARNINGS | ||
|
||
# You can also make your code fail to compile if you use deprecated APIs. | ||
# In order to do so, uncomment the following line. | ||
# You can also select to disable deprecated APIs only up to a certain version of Qt. | ||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 | ||
|
||
CONFIG += c++11 | ||
|
||
SOURCES += \ | ||
main.cpp \ | ||
interface.cpp | ||
|
||
HEADERS += \ | ||
interface.h | ||
|
||
FORMS += \ | ||
interface.ui | ||
|
||
# Default rules for deployment. | ||
qnx: target.path = /tmp/$${TARGET}/bin | ||
else: unix:!android: target.path = /opt/$${TARGET}/bin | ||
!isEmpty(target.path): INSTALLS += target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
### Specify your qt install location here | ||
### Ex. /opt/qt/5.12.0/gcc_64 | ||
QT_DIR = /opt/qt/5.12.1/gcc_64 | ||
|
||
CXX = g++ | ||
UIC = $(QT_DIR)/bin/uic | ||
MOC = $(QT_DIR)/bin/moc | ||
BUILD_DIR = ./build/ | ||
DEFINES = -DQT_DEPRECATED_WARNINGS -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB | ||
CXXFLAGS = -pipe -O2 -std=gnu++11 -Wall -W -D_REENTRANT -fPIC $(DEFINES) | ||
INCPATH = -I. -I$(QT_DIR)/include -I$(QT_DIR)/include/QtWidgets -I$(QT_DIR)/include/QtGui -I$(QT_DIR)/include/QtCore | ||
LFLAGS = -Wl,-O1 -Wl,-rpath,$(QT_DIR)/lib | ||
LIBS = -L$(QT_DIR)/lib -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread | ||
SOURCES = main.cpp interface.cpp moc_interface.cpp | ||
OBJECTS = $(patsubst %.cpp, %.o, $(SOURCES)) | ||
EXEOJBS = $(addprefix $(BUILD_DIR), $(OBJECTS)) | ||
UIHEADER = ui_interface.h | ||
MOCCXX = moc_interface.cpp | ||
TARGET = Basic_image_processing | ||
|
||
all: build_dir $(TARGET) | ||
|
||
$(TARGET): $(UIHEADER) $(EXEOJBS) | ||
$(CXX) $(LFLAGS) -o $(TARGET) $(EXEOJBS) $(LIBS) | ||
|
||
$(BUILD_DIR)%.o: %.cpp | ||
$(CXX) $(CXXFLAGS) $(INCPATH) -c $< -o $@ | ||
|
||
$(MOCCXX): interface.h | ||
$(MOC) $(DEFINES) $(INCPATH) interface.h -o $@ | ||
|
||
$(UIHEADER): interface.ui | ||
$(UIC) interface.ui -o $@ | ||
|
||
build_dir: | ||
mkdir -p $(BUILD_DIR) | ||
|
||
clean: | ||
rm -rf $(BUILD_DIR) $(TARGET) $(MOCCXX) $(UIHEADER) | ||
|
||
.PHONY: clean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Basic Image Processing - Qt | ||
This is a basic linux GUI written with [Qt][qt-link] that do some basic image processing task. \ | ||
At current state it contains following functionalities: | ||
1. Loading and saving .jpg .png .bmp image files. | ||
2. Image inversion. | ||
3. Histogram equalization. | ||
4. Gamma correction based on user input gamma value. | ||
|
||
[qt-link]: https://www.qt.io/ | ||
|
||
### Requirements: | ||
GNU-g++, make, Qt community version>=4 | ||
|
||
### Program compile: | ||
Specify the Qt installation location in Makefile and type ```make``` under the project directory. | ||
|
||
### Downloads | ||
Check the [release][release-link] page | ||
|
||
[release-link]: https://github.com/timforce/Basic_Image_Processing-Qt/releases |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
#include "interface.h" | ||
#include "ui_interface.h" | ||
#include <math.h> | ||
|
||
Interface::Interface(QWidget *parent) : | ||
QMainWindow(parent), | ||
ui(new Ui::Interface) | ||
{ | ||
ui->setupUi(this); | ||
ui->status->setText("Welcome!"); | ||
this->setFixedSize(QSize(850, 550)); | ||
} | ||
|
||
Interface::~Interface() | ||
{ | ||
delete ui; | ||
} | ||
|
||
void Interface::on_actionOpen_triggered() | ||
{ | ||
QString filename = QFileDialog::getOpenFileName(this, "Open Image File", nullptr, | ||
"Images (*.jpg *.jpeg *.JPG *.png *.PNG *.bmp *.BMP );;" | ||
"JPG (*.jpg *.jpeg *.JPG);;" | ||
"PNG (*.png *.PNG);;" | ||
"BMP (*.bmp *.BMP)"); | ||
if(!original_img.load(filename)) | ||
{ | ||
if(static_cast<bool>(proc_stat & img_loaded)) | ||
return; | ||
ui->status->setText("Didn't load the image!"); | ||
proc_stat = 0; | ||
return; | ||
} | ||
else { | ||
processed_img = original_img.copy(); | ||
ui->orig_frame->setPixmap(original_img.scaled(ui->orig_frame->size(), Qt::KeepAspectRatio)); | ||
ui->proc_frame->setPixmap(processed_img.scaled(ui->proc_frame->size(), Qt::KeepAspectRatio)); | ||
ui->status->setText("Loaded image: " + filename); | ||
proc_stat = 1; | ||
} | ||
} | ||
|
||
void Interface::on_imgInv_clicked() | ||
{ | ||
if (check_status(inv_done)) | ||
return; | ||
QImage proc = original_img.copy().toImage(); | ||
uchar *bit = proc.bits(); | ||
int h = proc.height(); | ||
int w = proc.width(); | ||
int i, j, dest_index; | ||
for(i = 0; i < w; ++i){ | ||
for(j = 0; j < h; ++j){ | ||
dest_index = 4*i + 4*w*j; | ||
bit[dest_index + 0 ] = ~(bit[dest_index + 0]); | ||
bit[dest_index + 1 ] = ~(bit[dest_index + 1]); | ||
bit[dest_index + 2 ] = ~(bit[dest_index + 2]); | ||
} | ||
} | ||
processed_img = processed_img.fromImage(proc); | ||
ui->proc_frame->setPixmap(processed_img.scaled(ui->proc_frame->size(), Qt::KeepAspectRatio)); | ||
ui->status->setText("Image inversion done!"); | ||
proc_stat |= inv_done; | ||
} | ||
|
||
void Interface::on_imgHistEql_clicked() | ||
{ | ||
if (check_status(hist_done)) | ||
return; | ||
QImage proc = original_img.copy().toImage(); | ||
uchar *bit = proc.bits(); | ||
int h = proc.height(); | ||
int w = proc.width(); | ||
int pixels = w*h; | ||
int i, j, dest_index; | ||
float *crfR = new float[256] (); | ||
float *crfG = new float[256] (); | ||
float *crfB = new float[256] (); | ||
for(i = 0; i < w; ++i){ | ||
for(j = 0; j < h; ++j){ | ||
dest_index = 4*i + 4*w*j; | ||
crfR[static_cast<int>(bit[dest_index + 0])]++; | ||
crfG[static_cast<int>(bit[dest_index + 1])]++; | ||
crfB[static_cast<int>(bit[dest_index + 2])]++; | ||
} | ||
} | ||
for(i = 1; i <= 255; i++) | ||
{ | ||
crfR[i] += crfR[i-1]; | ||
crfG[i] += crfG[i-1]; | ||
crfB[i] += crfB[i-1]; | ||
} | ||
for(i = 0; i < w; ++i){ | ||
for(j = 0; j < h; ++j){ | ||
dest_index = 4*i + 4*w*j; | ||
bit[dest_index+0] = static_cast<uchar>( | ||
static_cast<int>((crfR[static_cast<int>(bit[dest_index+0])] / pixels * 255))); | ||
bit[dest_index+1] = static_cast<uchar>( | ||
static_cast<int>((crfG[static_cast<int>(bit[dest_index+1])] / pixels * 255))); | ||
bit[dest_index+2] = static_cast<uchar>( | ||
static_cast<int>((crfB[static_cast<int>(bit[dest_index+2])] / pixels * 255))); | ||
} | ||
} | ||
delete[] crfR; | ||
delete[] crfG; | ||
delete[] crfB; | ||
processed_img = processed_img.fromImage(proc); | ||
ui->proc_frame->setPixmap(processed_img.scaled(ui->proc_frame->size(), Qt::KeepAspectRatio)); | ||
ui->status->setText("Histogram equalization done!"); | ||
proc_stat |= hist_done; | ||
} | ||
|
||
void Interface::on_imgGammaCor_clicked() | ||
{ | ||
if(check_status()) | ||
return; | ||
QRegExp reg("[-+]?[0-9.]*"); | ||
QString gamma_in = ui->gamma_input->text(); | ||
double gamma_val; | ||
if(reg.exactMatch(gamma_in)) | ||
gamma_val = gamma_in.toDouble(); | ||
else{ | ||
ui->status->setText("Please set a valid value for gamma"); | ||
return; | ||
} | ||
QImage proc = original_img.copy().toImage(); | ||
uchar *bit = proc.bits(); | ||
int h = proc.height(); | ||
int w = proc.width(); | ||
int i, j, dest_index; | ||
for(i = 0; i < w; ++i){ | ||
for(j = 0; j < h; ++j){ | ||
dest_index = 4*i + 4*w*j; | ||
bit[dest_index+0] = static_cast<uchar>( | ||
static_cast<int>(255 * pow(static_cast<double>(bit[dest_index+0]) / 255, gamma_val))); | ||
bit[dest_index+1] = static_cast<uchar>( | ||
static_cast<int>(255 * pow(static_cast<double>(bit[dest_index+1]) / 255, gamma_val))); | ||
bit[dest_index+2] = static_cast<uchar>( | ||
static_cast<int>(255 * pow(static_cast<double>(bit[dest_index+2]) / 255, gamma_val))); | ||
} | ||
} | ||
processed_img = processed_img.fromImage(proc); | ||
ui->proc_frame->setPixmap(processed_img.scaled(ui->proc_frame->size(), Qt::KeepAspectRatio)); | ||
ui->status->setText("Gamma correction done! Input gamma value: " + QString::number(gamma_val)); | ||
proc_stat |= gamma_done; | ||
} | ||
|
||
|
||
void Interface::on_imgReset_clicked() | ||
{ | ||
if(check_status()) | ||
return; | ||
processed_img = original_img.copy(); | ||
ui->proc_frame->setPixmap(processed_img.scaled(ui->proc_frame->size(), Qt::KeepAspectRatio)); | ||
ui->status->setText("Image reset to default state."); | ||
} | ||
|
||
void Interface::on_actionSave_as_triggered() | ||
{ | ||
if(check_status()) | ||
return; | ||
QString saveFileName = QFileDialog::getSaveFileName(this, "Save processed image as..", "output.jpg", | ||
"jpg, png, bmp (*.jpg, *.png *.bmp)"); | ||
QString ext = QFileInfo(saveFileName).suffix(); | ||
QPixmap pixmap; | ||
if(ext=="jpg" || ext=="png" || ext=="bmp") | ||
{ | ||
QFile outfile(saveFileName); | ||
if (!outfile.open(QFile::WriteOnly)){ | ||
QMessageBox::warning(this, "Warning", "Cannot save file: " + outfile.errorString()); | ||
return; | ||
} | ||
processed_img.save(&outfile); | ||
ui->status->setText("Saved processed image to: " + saveFileName); | ||
} | ||
} | ||
|
||
bool Interface::check_status(void) | ||
{ | ||
if(!static_cast<bool>(proc_stat & img_loaded)) | ||
{ | ||
QMessageBox::information(this, "Info", "Please load an image file first"); | ||
return true; | ||
} | ||
proc_stat = 1; | ||
return false; | ||
} | ||
|
||
bool Interface::check_status(const uchar proc) | ||
{ | ||
if(static_cast<bool>(proc_stat & proc)) | ||
return true; | ||
if(check_status()) | ||
return true; | ||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#ifndef INTERFACE_H | ||
#define INTERFACE_H | ||
|
||
#include <QMainWindow> | ||
#include <QFile> | ||
#include <QFileDialog> | ||
#include <QBuffer> | ||
#include <QImage> | ||
#include <QPixmap> | ||
#include <QMessageBox> | ||
|
||
namespace Ui { | ||
class Interface; | ||
} | ||
|
||
class Interface : public QMainWindow | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
explicit Interface(QWidget *parent = nullptr); | ||
~Interface(); | ||
|
||
private slots: | ||
void on_actionOpen_triggered(); | ||
|
||
void on_imgInv_clicked(); | ||
|
||
void on_imgHistEql_clicked(); | ||
|
||
void on_imgGammaCor_clicked(); | ||
|
||
void on_actionSave_as_triggered(); | ||
|
||
void on_imgReset_clicked(); | ||
|
||
private: | ||
Ui::Interface *ui; | ||
QPixmap original_img; | ||
QPixmap processed_img; | ||
uchar proc_stat = 0; | ||
const uchar img_loaded = 1 << 0; | ||
const uchar hist_done = 1 << 1; | ||
const uchar gamma_done = 1 << 2; | ||
const uchar inv_done = 1 << 3; | ||
bool check_status(void); | ||
bool check_status(const uchar); | ||
}; | ||
|
||
#endif // INTERFACE_H |
Oops, something went wrong.