//AdaptiveThreshold.h
#ifndef ADAPTIVETHRESHOLD_H
#define ADAPTIVETHRESHOLD_H
#include "cv.h"
#include "highgui.h"
#include <QtCore/QObject>
#include <QtGui/QDialog>
#include <QtGui/QWidget>
#include <QtGui/QHBoxLayout>
#include <QtGui/QVBoxLayout>
#include <QtGui/QSlider>
#include <QtGui/QLabel>
#include <QtGui/QImage>
#include <QtGui/QPixmap>
#include <QtGui/QGroupBox>
#include <QtGui/QRadioButton>
#include <QtGui/QLineEdit>
#include <QtGui/QPushButton>
#include <QtGui/QFileDialog>
#include <QtGui/QComboBox>
class AdaptiveThreshold:public QDialog{
Q_OBJECT
public:
AdaptiveThreshold(IplImage* imgRGB,QWidget* parent=0,Qt::WindowFlags f=0);
~AdaptiveThreshold();
static void Ipl2QImageRGB32(IplImage* iplImage,QImage* qImage);
private Q_SLOTS:
void setBlockSizeValue();
void setParam1Value();
void meanThresholding();
void gaussianThresholding();
void doThresholding();
void saveThresholdedImage();
void exitDialog();
private:
//data
IplImage* m_imgRGB;
IplImage* m_imgGray;
IplImage* m_imgTresholding;
bool m_meanThresholdingFlag;
bool m_gaussianThresholdingFlag;
/*
** gui
*/
//main horizontal layout
QHBoxLayout* m_mainLayout;
//left vertical layout
QVBoxLayout* m_leftLayout;
//blockSizeSlider
QHBoxLayout* m_blockSizeSliderLayout;
QLabel* m_blockSizeSliderName;
QSlider* m_blockSizeSlider;
//param1ValueSlider
QHBoxLayout* m_param1ValueSliderLayout;
QLabel* m_param1ValueSliderName;
QSlider* m_param1ValueSlider;
//label for image
QLabel* m_imageLabel;
//right vertical layout
QVBoxLayout* m_rightLayout;
//thresholding type
QGroupBox* m_thresholdingType;
QVBoxLayout* m_thresholdingTypeLayout;
QRadioButton* m_meanTypeButton;
QRadioButton* m_gaussianTypeButton;
//parameter values
//block size
QHBoxLayout* m_blockSizeValueLayout;
QLabel* m_blockSizeValueName;
QLineEdit* m_blockSizeValue;
//param1
QHBoxLayout* m_param1ValueLayout;
QLabel* m_param1ValueName;
QLineEdit* m_param1Value;
//morphological processing
QComboBox* m_morphologicalType;
QSlider* m_morphologicalSlider;
//save the thresholded image
QPushButton* m_saveThresholdedImageButton;
//exit button
QPushButton* m_exitButton;
};
#endif
//AdaptiveThreshold.cpp
#include "AdaptiveThreshold.h"
AdaptiveThreshold::AdaptiveThreshold(IplImage *imgRGB, QWidget *parent, Qt::WindowFlags f):QDialog(parent,f){
m_imgRGB=cvCreateImage(cvSize(imgRGB->width,imgRGB->height),imgRGB->depth,imgRGB->nChannels);
cvCopy(imgRGB,m_imgRGB);
m_imgGray=cvCreateImage(cvSize(imgRGB->width,imgRGB->height),imgRGB->depth,1);
cvCvtColor(m_imgRGB,m_imgGray,CV_RGB2GRAY);
cvSmooth(m_imgGray,m_imgGray,CV_GAUSSIAN,3,3);
m_imgTresholding=cvCreateImage(cvSize(m_imgGray->width,m_imgGray->height),m_imgGray->depth,m_imgGray->nChannels);
m_meanThresholdingFlag=false;
m_gaussianThresholdingFlag=false;
//gui
//main horizontal layout
m_mainLayout=new QHBoxLayout();
//left layout
m_leftLayout=new QVBoxLayout();
//blockSizeSlider
m_blockSizeSliderLayout=new QHBoxLayout();
m_blockSizeSliderName=new QLabel(tr("Block Size"));
m_blockSizeSlider=new QSlider(Qt::Horizontal);
m_blockSizeSlider->setMinimum(0);
m_blockSizeSlider->setMaximum(20);
m_blockSizeSlider->setSingleStep(1);
m_blockSizeSlider->setPageStep(1);
m_blockSizeSlider->setValue(0);
m_blockSizeSlider->setEnabled(false);
QObject::connect(m_blockSizeSlider,SIGNAL(valueChanged(int)),this,SLOT(setBlockSizeValue()));
QObject::connect(m_blockSizeSlider,SIGNAL(valueChanged(int)),this,SLOT(doThresholding()));
m_blockSizeSliderName->setBuddy(m_blockSizeSlider);
m_blockSizeSliderLayout->addWidget(m_blockSizeSliderName);
m_blockSizeSliderLayout->addWidget(m_blockSizeSlider);
m_leftLayout->addLayout(m_blockSizeSliderLayout);
//param1ValueSlider
m_param1ValueSliderLayout=new QHBoxLayout();
m_param1ValueSliderName=new QLabel(tr("Param1 Value"));
m_param1ValueSlider=new QSlider(Qt::Horizontal);
m_param1ValueSlider->setMaximum(1000);
m_param1ValueSlider->setMinimum(-1000);
m_param1ValueSlider->setSingleStep(1);
m_param1ValueSlider->setValue(0);
m_param1ValueSlider->setPageStep(1);
m_param1ValueSlider->setEnabled(false);
QObject::connect(m_param1ValueSlider,SIGNAL(valueChanged(int)),this,SLOT(setParam1Value()));
QObject::connect(m_param1ValueSlider,SIGNAL(valueChanged(int)),this,SLOT(doThresholding()));
m_param1ValueSliderName->setBuddy(m_param1ValueSlider);
m_param1ValueSliderLayout->addWidget(m_param1ValueSliderName);
m_param1ValueSliderLayout->addWidget(m_param1ValueSlider);
m_leftLayout->addLayout(m_param1ValueSliderLayout);
//label for image
m_imageLabel=new QLabel();
QImage* qImage=new QImage(m_imgRGB->width,m_imgRGB->height,QImage::Format_RGB32);
Ipl2QImageRGB32(m_imgRGB,qImage);
QPixmap* pixmapImage=new QPixmap();
m_imageLabel->setPixmap(pixmapImage->fromImage(*qImage));
m_leftLayout->addWidget(m_imageLabel);
//right layout
m_rightLayout=new QVBoxLayout();
m_thresholdingType=new QGroupBox(tr("types of thresholding"));
m_thresholdingTypeLayout=new QVBoxLayout();
m_meanTypeButton=new QRadioButton(tr("mean"),m_thresholdingType);
m_thresholdingTypeLayout->addWidget(m_meanTypeButton);
QObject::connect(m_meanTypeButton,SIGNAL(clicked()),this,SLOT(meanThresholding()));
m_gaussianTypeButton=new QRadioButton(tr("gaussian"),m_thresholdingType);
m_thresholdingTypeLayout->addWidget(m_gaussianTypeButton);
QObject::connect(m_gaussianTypeButton,SIGNAL(clicked()),this,SLOT(gaussianThresholding()));
m_thresholdingType->setLayout(m_thresholdingTypeLayout);
m_rightLayout->addWidget(m_thresholdingType);
//parameter values
//block size
m_blockSizeValueLayout=new QHBoxLayout();
m_blockSizeValueName=new QLabel(tr("Block Size"));
m_blockSizeValue=new QLineEdit();
m_blockSizeValueName->setBuddy(m_blockSizeValue);
m_blockSizeValue->setText(QString::number((double)(m_blockSizeSlider->value()*2+3)));
m_blockSizeValueLayout->addWidget(m_blockSizeValueName);
m_blockSizeValueLayout->addWidget(m_blockSizeValue);
m_rightLayout->addLayout(m_blockSizeValueLayout);
//param1
m_param1ValueLayout= new QHBoxLayout();
m_param1ValueName=new QLabel("Param1 value");
m_param1Value= new QLineEdit();
m_param1ValueName->setBuddy(m_param1Value);
m_param1Value->setText(QString::number((double)m_param1ValueSlider->value()));
m_param1ValueLayout->addWidget(m_param1ValueName);
m_param1ValueLayout->addWidget(m_param1Value);
m_rightLayout->addLayout(m_param1ValueLayout);
//morphological processing
m_morphologicalType=new QComboBox();
m_morphologicalType->addItem(QString("Open"));
m_morphologicalType->addItem(QString("Close"));
m_rightLayout->addWidget(m_morphologicalType);
m_morphologicalSlider=new QSlider(Qt::Horizontal);
m_morphologicalSlider->setMinimum(0);
m_morphologicalSlider->setMaximum(7);
m_morphologicalSlider->setSingleStep(1);
m_morphologicalSlider->setPageStep(1);
m_morphologicalSlider->setValue(0);
m_morphologicalSlider->setEnabled(false);
m_rightLayout->addWidget(m_morphologicalSlider);
QObject::connect(m_morphologicalSlider,SIGNAL(valueChanged(int)),this,SLOT(doThresholding()));
//save the thresholded image
m_saveThresholdedImageButton=new QPushButton(tr("&Save Thresholded Image"));
m_rightLayout->addWidget(m_saveThresholdedImageButton);
QObject::connect(m_saveThresholdedImageButton,SIGNAL(clicked()),this,SLOT(saveThresholdedImage()));
//exit button
m_exitButton=new QPushButton(tr("&Exit"));
m_rightLayout->addWidget(m_exitButton);
QObject::connect(m_exitButton,SIGNAL(clicked()),this,SLOT(exitDialog()));
m_mainLayout->addLayout(m_leftLayout);
m_mainLayout->addLayout(m_rightLayout);
this->setLayout(m_mainLayout);
}
AdaptiveThreshold::~AdaptiveThreshold(){
cvReleaseImage(&m_imgRGB);
cvReleaseImage(&m_imgGray);
cvReleaseImage(&m_imgTresholding);
}
void AdaptiveThreshold::setBlockSizeValue(){
m_blockSizeValue->setText(QString::number((double)(m_blockSizeSlider->value()*2+3)));
}
void AdaptiveThreshold::setParam1Value(){
m_param1Value->setText(QString::number(((double)m_param1ValueSlider->value())/10.0));
}
void AdaptiveThreshold::meanThresholding(){
if(!m_blockSizeSlider->isEnabled()){
m_blockSizeSlider->setEnabled(true);
}
if(!m_param1ValueSlider->isEnabled()){
m_param1ValueSlider->setEnabled(true);
}
if(!m_morphologicalSlider->isEnabled()){
m_morphologicalSlider->setEnabled(true);
}
m_meanThresholdingFlag=true;
m_gaussianThresholdingFlag=false;
doThresholding();
}
void AdaptiveThreshold::gaussianThresholding(){
if(!m_blockSizeSlider->isEnabled()){
m_blockSizeSlider->setEnabled(true);
}
if(!m_param1ValueSlider->isEnabled()){
m_param1ValueSlider->setEnabled(true);
}
if(!m_morphologicalSlider->isEnabled()){
m_morphologicalSlider->setEnabled(true);
}
m_meanThresholdingFlag=false;
m_gaussianThresholdingFlag=true;
doThresholding();
}
void AdaptiveThreshold::doThresholding(){
//thresholding
if(m_meanThresholdingFlag){
cvAdaptiveThreshold(m_imgGray,m_imgTresholding,255.0,CV_ADAPTIVE_THRESH_MEAN_C,CV_THRESH_BINARY,m_blockSizeSlider->value()*2+3,((double)m_param1ValueSlider->value())/10.0);
}
else if(m_gaussianThresholdingFlag){
cvAdaptiveThreshold(m_imgGray,m_imgTresholding,255.0,CV_ADAPTIVE_THRESH_GAUSSIAN_C,CV_THRESH_BINARY,m_blockSizeSlider->value()*2+3,((double)m_param1ValueSlider->value())/10.0);
}
//morphological processing
IplConvKernel* crossKernel=cvCreateStructuringElementEx(m_morphologicalSlider->value()*2+3,m_morphologicalSlider->value()*2+3,m_morphologicalSlider->value()+1,m_morphologicalSlider->value()+1,CV_SHAPE_CROSS);
if(m_morphologicalType->currentText().compare(QString("Open"))==0){
cvMorphologyEx(m_imgTresholding,m_imgTresholding,0,crossKernel,CV_MOP_OPEN);
}
else if(m_morphologicalType->currentText().compare(QString("Close"))==0){
cvMorphologyEx(m_imgTresholding,m_imgTresholding,0,crossKernel,CV_MOP_CLOSE);
}
QImage* qImage=new QImage(m_imgTresholding->width,m_imgTresholding->height,QImage::Format_RGB32);
Ipl2QImageRGB32(m_imgTresholding,qImage);
QPixmap* pixmapImage=new QPixmap();
m_imageLabel->setPixmap(pixmapImage->fromImage(*qImage));
}
void AdaptiveThreshold::saveThresholdedImage(){
QString imgName=QFileDialog::getSaveFileName(0,tr("Save Thresholded Image Name"),"thresholdedImage.jpg",tr("Image (*.jpg)"));
cvSaveImage(imgName.toLatin1().data(),m_imgTresholding);
}
void AdaptiveThreshold::exitDialog(){
this->done(1);
}
void AdaptiveThreshold::Ipl2QImageRGB32(IplImage* iplImage,QImage* qImage){
unsigned char* ptrQImage=qImage->bits();
switch(iplImage->depth){
case IPL_DEPTH_8U:
if(iplImage->nChannels==1){
for(int row=0;row<iplImage->height;row++){
unsigned char* ptr=(unsigned char*)(iplImage->imageData+row*iplImage->widthStep);
for(int col=0;col<iplImage->width;col++){
*(ptrQImage)=*(ptr+col);
*(ptrQImage+1)=*(ptr+col);
*(ptrQImage+2)=*(ptr+col);
*(ptrQImage+3)=0;
ptrQImage+=4;
}
}
}
else if(iplImage->nChannels==3){
for(int row=0;row<iplImage->height;row++){
unsigned char* ptr=(unsigned char*)(iplImage->imageData+row*iplImage->widthStep);
for(int col=0;col<iplImage->width;col++){
*(ptrQImage)=*(ptr+col*3);
*(ptrQImage+1)=*(ptr+col*3+1);
*(ptrQImage+2)=*(ptr+col*3+2);
*(ptrQImage+3)=0;
ptrQImage+=4;
}
}
}
break;
case IPL_DEPTH_32F:
if(iplImage->nChannels==1){
for(int row=0;row<iplImage->height;row++){
float* ptr=(float*)(iplImage->imageData+row*iplImage->widthStep);
for(int col=0;col<iplImage->width;col++){
*(ptrQImage)=(unsigned char)(*(ptr+col)*255.0);
*(ptrQImage+1)=(unsigned char)(*(ptr+col)*255.0);
*(ptrQImage+2)=(unsigned char)(*(ptr+col)*255.0);
*(ptrQImage+3)=0;
ptrQImage+=4;
}
}
}
else if(iplImage->nChannels==3){
for(int row=0;row<iplImage->height;row++){
float* ptr=(float*)(iplImage->imageData+row*iplImage->widthStep);
for(int col=0;col<iplImage->width;col++){
*(ptrQImage)=(unsigned char)(*(ptr+col*3)*255.0);
*(ptrQImage+1)=(unsigned char)(*(ptr+col*3+1)*255.0);
*(ptrQImage+2)=(unsigned char)(*(ptr+col*3+2)*255.0);
*(ptrQImage+3)=0;
ptrQImage+=4;
}
}
}
break;
case IPL_DEPTH_64F:
if(iplImage->nChannels==1){
for(int row=0;row<iplImage->height;row++){
double* ptr=(double*)(iplImage->imageData+row*iplImage->widthStep);
for(int col=0;col<iplImage->width;col++){
*(ptrQImage)=(unsigned char)(*(ptr+col)*255.0);
*(ptrQImage+1)=(unsigned char)(*(ptr+col)*255.0);
*(ptrQImage+2)=(unsigned char)(*(ptr+col)*255.0);
*(ptrQImage+3)=0;
ptrQImage+=4;
}
}
}
else if(iplImage->nChannels==3){
for(int row=0;row<iplImage->height;row++){
double* ptr=(double*)(iplImage->imageData+row*iplImage->widthStep);
for(int col=0;col<iplImage->width;col++){
*(ptrQImage)=(unsigned char)(*(ptr+col*3)*255.0);
*(ptrQImage+1)=(unsigned char)(*(ptr+col*3+1)*255.0);
*(ptrQImage+2)=(unsigned char)(*(ptr+col*3+2)*255.0);
*(ptrQImage+3)=0;
ptrQImage+=4;
}
}
}
break;
default:
printf("The type of the IplImage should be IPL_DEPTH_8U,IPL_DEPTH_32F or IPL_DEPTH_64F");
}
}
//main.cpp
#include "AdaptiveThreshold.h"
#include <QtGui/QApplication>
int main(int argc,char** argv){
QApplication app(argc,argv);
IplImage* img=cvLoadImage("data/videoImage.jpg",1);
AdaptiveThreshold testDialog(img);
int ret=testDialog.exec();
return app.exec();
}