PDA

View Full Version : slider and color filtering or thresholding



rcmandar
28th October 2014, 01:55
hello guys,


i want to make an app to track an Object.

I am using opencv. I want change color threshold values using QSliders. However, i am unable to do so.
Please see attached pic along with the code.

Notice all the zeros in plainTextedit. Even if i change the slider position my variables ch1_min and others change. However, i still have 0 numbers for this in inRange function in the code.

Please help.


#include "dialog.h"
#include "ui_dialog.h"

//////////////////////////////////////////////////////////////////////////
/// \brief -> this is the Constructor
/// \param parent
//////////////////////////////////////////////////////////////////////////

Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog)
{
ui->setupUi(this);
timer1 = new QTimer(this);
connect(timer1, SIGNAL(timeout()), this, SLOT(ShowCamera()));
ch1_min = ch2_min = ch3_min = 0;
ch1_max = ch2_max = ch3_max = 255;
}
//////////////////////////////////////////////////////////////////////////
/// \brief -> this is the Deconstructor
//////////////////////////////////////////////////////////////////////////
Dialog::~Dialog()
{
delete ui;
}
/////////////////////////////////////////////////////////////////////////////
/// \brief Dialog::Dialog::paintEvent -> putText function
/// \param e
/////////////////////////////////////////////////////////////////////////////
/*void Dialog::putText(QPaintEvent *e)
{
QPainter painter(&tempframe);
QPen ourpen(Qt::magenta);
ourpen.setWidth(2);
painter.setPen(ourpen);
painter.setFont(QFont("Times", 20, QFont::Bold));
painter.drawText(outputView.rect(), "THIS!!"); ////////////// doesn't work
}*/
//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Dialog::on_dispButton_clicked -> this function starts or stops the camera.
///
///
/////////////////////////////////////////////////////////////////////////////////////////////

void Dialog::on_dispButton_clicked()
{
if(timer1->isActive() == true)
{
ui->dispButton->setText("Start camView");
timer1->stop();
cameraFeed.release();
ui->camView->setText("Your camera view will be available here.");

}
else
{
ui->dispButton->setText("Stop camView");
timer1->start(30);
Camera.open(0);

}

}



//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief all sliderMoved to change channel min and max
/// \param ch1_min ch2_min ch3_min ch1_max ch2_max ch3_max
/////////////////////////////////////////////////////////////////////////////////////////////
void Dialog::on_ch1min_sliderMoved(int ch1_min)
{
ui->ch1min->valueChanged(ch1_min);
if(ch1_min < ch1_max)
{

ch1_min_string = QString::number(ch1_min);
ui->dsp_ch1_min->clear();
ui->dsp_ch1_min->appendPlainText(ch1_min_string);
}
else
{
ch1_min = ch1_max-1;
ui->ch1min->valueChanged(ch1_min);
ch1_min_string = QString::number(ch1_min);
ui->dsp_ch1_min->clear();
ui->dsp_ch1_min->appendPlainText(ch1_min_string);
}
}

void Dialog::on_ch2min_sliderMoved(int ch2_min)
{
ui->ch2min->valueChanged(ch2_min);
if(ch2_min < ch2_max)
{

ch2_min_string = QString::number(ch2_min);
ui->dsp_ch2_min->clear();
ui->dsp_ch2_min->appendPlainText(ch2_min_string);
}
else
{
ch2_min = ch2_max-1;
ui->ch2min->valueChanged(ch2_min);
ch2_min_string = QString::number(ch2_min);
ui->dsp_ch2_min->clear();
ui->dsp_ch2_min->appendPlainText(ch2_min_string);
}
}

void Dialog::on_ch3min_sliderMoved(int ch3_min)
{
ui->ch3min->valueChanged(ch3_min);
if(ch3_min < ch3_max)
{

ch3_min_string = QString::number(ch3_min);
ui->dsp_ch3_min->clear();
ui->dsp_ch3_min->appendPlainText(ch3_min_string);
}
else
{
ch3_min = ch3_max-1;
ui->ch3min->valueChanged(ch3_min);
ch3_min_string = QString::number(ch3_min);
ui->dsp_ch3_min->clear();
ui->dsp_ch3_min->appendPlainText(ch3_min_string);
}
}

void Dialog::on_ch1max_sliderMoved(int ch1_max)
{
ui->ch1max->valueChanged(ch1_max);
if(ch1_max > ch1_min)
{
ch1_max_string = QString::number(ch1_max);
ui->dsp_ch1_max->clear();
ui->dsp_ch1_max->appendPlainText(ch1_max_string);
}
else
{
ch1_max= ch1_min+1;
ch1_max_string = QString::number(ch1_max);
ui->dsp_ch1_max->clear();
ui->dsp_ch1_max->appendPlainText(ch1_max_string);
}

}

void Dialog::on_ch2max_sliderMoved(int ch2_max)
{
ui->ch2max->valueChanged(ch2_max);
if(ch2_max>ch2_min)
{
ch2_max_string = QString::number(ch2_max);
ui->dsp_ch2_max->clear();
ui->dsp_ch2_max->appendPlainText(ch2_max_string);
}
else
{
ch2_max = ch2_min+1;
ch2_max_string = QString::number(ch2_max);
ui->dsp_ch2_max->clear();
ui->dsp_ch2_max->appendPlainText(ch2_max_string);
}
}

void Dialog::on_ch3max_sliderMoved(int ch3_max)
{
ui->ch3max->valueChanged(ch3_max);
if(ch3_max>ch3_min)
{
ch3_max_string = QString::number(ch3_max);
ui->dsp_ch3_max->clear();
ui->dsp_ch3_max->appendPlainText(ch3_max_string);
}
else
{
ch3_max=ch3_min+1;
ch3_max_string = QString::number(ch3_max);
ui->dsp_ch3_max->clear();
ui->dsp_ch3_max->appendPlainText(ch3_max_string);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Dialog::ShowCamera -> here we read frames and show them in label called camView
/// temp is used only to make use of visual representation of image in Qt using QImage.
///
////////////////////////////////////////////////////////////////////////////////////////////////
void Dialog::ShowCamera()
{
Camera.read(cameraFeed);

ui->plainTextEdit->appendPlainText((QString::number(ch1_min))); ////this is the reason of all the zeros in plainTextEdit. for this function changed values do not appear updated

cv::inRange(cameraFeed,cv::Scalar(ch1_min,ch2_min, ch3_min),cv::Scalar(ch1_max,ch2_max,ch3_max),thres holdFeed);
if(cameraFeed.empty() == true) return;

////////////////// visualization of image acquired from camera

cameraFeed.copyTo(temp);
cv::cvtColor(temp, temp, CV_BGR2RGB);
QImage qimgOriginal((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);


////////////////// visualization of binary image

QImage qimgProcessed((uchar*) thresholdFeed.data, thresholdFeed.cols, thresholdFeed.rows, thresholdFeed.step, QImage::Format_Indexed8);
ui->camView->setPixmap(QPixmap::fromImage(qimgOriginal));
ui->outputView->setPixmap(QPixmap::fromImage(qimgProcessed));



}

wysota
28th October 2014, 07:20
valueChanged() is a signal and not a method for reading values from widgets. You should simply connect the valueChanged signal from a slider to the setValue slot from the spinbox and vice versa. Then connect to the valueChanged signal of one of those widgets to a custom slot accepting an integer which is going to contain the value you can use directly.

rcmandar
28th October 2014, 07:52
Then connect to the valueChanged signal of one of those widgets to a custom slot accepting an integer which is going to contain the value you can use directly.


Ohhh yes. I understand however.
I am not able to write
connect(ch1min, SIGNAL(valuechanged(int)), this, changeval1(int));

Coz i do not have ch1min available in dialog.cpp because i have draen sliders using gui of qt. Further i do not have change1val(int) available in gui design so that i can add a signal anx slot connection.

Please help.

wysota
28th October 2014, 09:09
because i have draen sliders using gui of qt.
I don't see how that matters.

rcmandar
28th October 2014, 10:49
i defined another set of variables and did rmin =ch1_min; when sliderMoved or spinBoxvalueChanged.

however i am now baffled by this opencv error:


OpenCV Error: Bad flag (parameter or structure field) (Unrecognized or unsupported array type) in cvGetMat, file /home/madmandy/opencv-2.4.9/modules/core/src/array.cpp, line 2482
terminate called after throwing an instance of 'cv::Exception'
what(): /home/madmandy/opencv-2.4.9/modules/core/src/array.cpp:2482: error: (-206) Unrecognized or unsupported array type in function cvGetMat

it is due to function trackLP. please help. i tried everything else form google searches.



#include "dialog.h"
#include "ui_dialog.h"

//////////////////////////////////////////////////////////////////////////
/// \brief -> this is the Constructor
/// \param parent
//////////////////////////////////////////////////////////////////////////

Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog)
{
ui->setupUi(this);
timer1 = new QTimer(this);
connect(timer1, SIGNAL(timeout()), this, SLOT(ShowCamera()));
ch1_min = ch2_min = ch3_min = 0;
ch1_max = ch2_max = ch3_max = 255;
rmin = gmin = bmin = 0;
rmax = gmax = bmax = 255;
}
//////////////////////////////////////////////////////////////////////////
/// \brief -> this is the Deconstructor
//////////////////////////////////////////////////////////////////////////
Dialog::~Dialog()
{
delete ui;
}

/*
/////////////////////////////////////////////////////////////////////////////
/// \brief Dialog::Dialog::paintEvent -> putText function
/// \param e
/////////////////////////////////////////////////////////////////////////////
void Dialog::putText(QPaintEvent *e)
{
QPainter painter(&tempframe);
QPen ourpen(Qt::magenta);
ourpen.setWidth(2);
painter.setPen(ourpen);
painter.setFont(QFont("Times", 20, QFont::Bold));
painter.drawText(outputView.rect(), "THIS!!");
}*/
//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Dialog::on_dispButton_clicked -> this function starts or stops the camera.
///
///
/////////////////////////////////////////////////////////////////////////////////////////////

void Dialog::on_dispButton_clicked()
{
if(timer1->isActive() == true)
{
ui->dispButton->setText("Start camView");
timer1->stop();
cameraFeed.release();
ui->camView->setText("Your camera view will be available here.");
thresholdFeed.release();
ui->outputView->setText("Your output view will be available here.");

}
else
{
ui->dispButton->setText("Stop camView");
timer1->start(30);
Camera.open(1); ///// 1 -> usb webcam

}

}
//////////////////////////////////////////////////////////////////////////////////////////////
/// \brief all sliderMoved and spinBox value changed to change channel min and max
/// \param ch1_min ch2_min ch3_min ch1_max ch2_max ch3_max
/// \param rmin gmin bmin rmax gmax bmax
/////////////////////////////////////////////////////////////////////////////////////////////


void Dialog::on_ch1min_sliderMoved(int ch1_min)
{

rmin = ch1_min;
}


void Dialog::on_ch1minspinBox_valueChanged(int ch1_min)
{
rmin = ch1_min;
}



void Dialog::on_ch2min_valueChanged(int ch2_min)
{
gmin = ch2_min;
}

void Dialog::on_ch2minspinBox_valueChanged(int ch2_min)
{
gmin = ch2_min;
}

void Dialog::on_ch3min_valueChanged(int ch3_min)
{
bmin = ch3_min;
}

void Dialog::on_ch3minspinBox_valueChanged(int ch3_min)
{
bmin = ch3_min;
}

void Dialog::on_ch1max_valueChanged(int ch1_max)
{
rmax = ch1_max;
}

void Dialog::on_ch1maxspinBox_valueChanged(int ch1_max)
{
rmax = ch1_max;
}

void Dialog::on_ch2max_valueChanged(int ch2_max)
{
gmax = ch2_max;
}

void Dialog::on_ch2maxspinBox_valueChanged(int ch2_max)
{
gmax = ch2_max;
}

void Dialog::on_ch3max_valueChanged(int ch3_max)
{
bmax = ch3_max;
}

void Dialog::on_ch3maxspinBox_valueChanged(int ch3_max)
{
bmax = ch3_max;
}

////////////////////////////////////////////////////////////////////////////////////////////////
/// \brief Dialog::ShowCamera -> here we read frames and show them in label called camView
/// temp is used only to make use of visual representation of image in Qt using QImage.
///
////////////////////////////////////////////////////////////////////////////////////////////////
void Dialog::ShowCamera()
{
Camera.read(cameraFeed); ////////////////it should be cameraFeed otherwise.
if(cameraFeed.empty() == true) return;

cv::inRange(cameraFeed,cv::Scalar(rmin,gmin,bmin), cv::Scalar(rmax,gmax,bmax),thresholdFeed);

morphOps(thresholdFeed);
trackLP(x, y, thresholdFeed);


////////////////// visualization of image acquired from camera

cameraFeed.copyTo(temp);
cv::cvtColor(temp, temp, CV_BGR2RGB);
QImage qimgOriginal((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);


////////////////// visualization of binary image

QImage qimgProcessed((uchar*) thresholdFeed.data, thresholdFeed.cols, thresholdFeed.rows, thresholdFeed.step, QImage::Format_Indexed8);

///////////////// show

ui->camView->setPixmap(QPixmap::fromImage(qimgOriginal));
ui->outputView->setPixmap(QPixmap::fromImage(qimgProcessed));

}


//////////////////////////////////////////////////////////////////////////////////////
/// \brief Dialog::morphOps -> morphological operations
/// \param thresh -> passed image from inRange to this
///////////////////////////////////////////////////////////////////////////////////////
void Dialog::morphOps(cv::Mat &threshMorph)
{
///create structuring element that will be used to "dilate" and "erode" image.
///the element chosen here is a 3px by 3px rectangle
cv::Mat erodeElement = getStructuringElement( cv::MORPH_RECT, cv::Size(3,3));
///dilate with larger element so make sure object is nicely visible
cv::Mat dilateElement = getStructuringElement( cv::MORPH_RECT,cv::Size(8,8));

cv::erode(threshMorph,threshMorph,erodeElement);
cv::erode(threshMorph,threshMorph,erodeElement);

cv::dilate(threshMorph,threshMorph,dilateElement);
cv::dilate(threshMorph,threshMorph,dilateElement);

}

/////////////////////////////////////////////////////////////////////////////////////////////
/// \brief trackLP -> this tracks the x,y coordinate from binary image
/// \param x -> x coordinate
/// \param y -> y coordinate
/// \param threshold -> binary image
/// \param cameraFeed -> acquired image from camera
//////////////////////////////////////////////////////////////////////////////////////////////
void Dialog::trackLP(int &x, int &y, cv::Mat &threshTrack) //////// cv::Mat &cameraFeed
{
threshTrack.copyTo(temp1);
cv::vector< cv::vector<cv::Point> > contours;
cv::vector<cv::Vec4i> hierarchy;
//find contours of filtered image using openCV findContours function
findContours(temp,contours,hierarchy,CV_RETR_CCOMP ,CV_CHAIN_APPROX_SIMPLE );
double refArea = 0;
bool objectFound = false;

if (hierarchy.size() > 0)
{
int numObjects = hierarchy.size();
//if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter
if(numObjects<MAX_NUM_OBJECTS)
{
for (int index = 0; index >= 0; index = hierarchy[index][0])
{
cv::Moments moment = cv::moments((cv::Mat)contours[index]);
double area = moment.m00;

//if the area is less than 5 px by 5 px then it is probably just noise
//if the area is the same as the 3/2 of the image size, probably just a bad filter
//we only want the object with the largest area so we safe a reference area each
//iteration and compare it to the area in the next iteration.
if(area>MIN_OBJ_AREA && area<MAX_OBJ_AREA && area>refArea)
{
x = moment.m10/area;
y = moment.m01/area;
objectFound = true;
refArea = area;
}
else objectFound = false;
}
//let user know you found an object
if(objectFound ==true)
{
ui->plainTextEdit->appendPlainText(QString("laser position: x=") + QString::number(x) + QString(" y=") + QString::number(y));

}
}
else
{
ui->plainTextEdit->appendPlainText(QString("still too much noise!"));
}
}

}