Skip to content
Snippets Groups Projects
Commit 32cf21ea authored by calrama's avatar calrama
Browse files

Fix violation of cv::BackgroundSubtractor API by previous implementation.

parent d722a18e
Branches
No related tags found
No related merge requests found
Pipeline #42525 passed
...@@ -77,21 +77,16 @@ void BioTrackerTrackingAlgorithm::sendSelectedImage(std::map<std::string, std::s ...@@ -77,21 +77,16 @@ void BioTrackerTrackingAlgorithm::sendSelectedImage(std::map<std::string, std::s
Q_EMIT emitChangeDisplayImage(QString("Background")); Q_EMIT emitChangeDisplayImage(QString("Background"));
break; break;
case 2: case 2:
sendImage = images->find(std::string("Foreground"))->second; sendImage = images->find(std::string("Foreground Mask"))->second;
Q_EMIT emitCvMatA(sendImage, QString("Foreground")); Q_EMIT emitCvMatA(sendImage, QString("Foreground Mask"));
Q_EMIT emitChangeDisplayImage(QString("Foreground")); Q_EMIT emitChangeDisplayImage(QString("Foreground Mask"));
break; break;
case 3: case 3:
sendImage = images->find(std::string("Binarized"))->second;
Q_EMIT emitCvMatA(sendImage, QString("Binarized"));
Q_EMIT emitChangeDisplayImage(QString("Binarized"));
break;
case 4:
sendImage = images->find(std::string("Eroded"))->second; sendImage = images->find(std::string("Eroded"))->second;
Q_EMIT emitCvMatA(sendImage, QString("Eroded")); Q_EMIT emitCvMatA(sendImage, QString("Eroded"));
Q_EMIT emitChangeDisplayImage(QString("Eroded")); Q_EMIT emitChangeDisplayImage(QString("Eroded"));
break; break;
case 5: case 4:
sendImage = images->find(std::string("Dilated"))->second; sendImage = images->find(std::string("Dilated"))->second;
Q_EMIT emitCvMatA(sendImage, QString("Dilated")); Q_EMIT emitCvMatA(sendImage, QString("Dilated"));
Q_EMIT emitChangeDisplayImage(QString("Dilated")); Q_EMIT emitChangeDisplayImage(QString("Dilated"));
......
...@@ -28,8 +28,8 @@ public slots: ...@@ -28,8 +28,8 @@ public slots:
Q_EMIT notifyView(); Q_EMIT notifyView();
}; };
double getBackgroundRatio() { return _LearningRate; }; double getLearningRate() { return _LearningRate; };
void setBackgroundRatio(double x) { void setLearningRate(double x) {
_LearningRate = x; _LearningRate = x;
Q_EMIT notifyView(); Q_EMIT notifyView();
}; };
......
...@@ -3,6 +3,13 @@ ...@@ -3,6 +3,13 @@
#include <vector> #include <vector>
#include <future> #include <future>
#include <opencv2/imgproc.hpp>
void CustomBackgroundSubtractor::setBinarizationThreshold(int value)
{
m_binarizationThreshold = value;
}
void CustomBackgroundSubtractor::getBackgroundImage(cv::OutputArray backgroundImage) const void CustomBackgroundSubtractor::getBackgroundImage(cv::OutputArray backgroundImage) const
{ {
m_background.copyTo(backgroundImage); m_background.copyTo(backgroundImage);
...@@ -24,13 +31,15 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgm ...@@ -24,13 +31,15 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgm
fgmask.create(imageHeight, imageWidth, image.type()); fgmask.create(imageHeight, imageWidth, image.type());
auto fgmaskmat = fgmask.getMat();
auto workOnRegion = [&](int x, int y) { auto workOnRegion = [&](int x, int y) {
const int startingX = x * regionWidth; const int startingX = x * regionWidth;
const int startingY = y * regionHeight; const int startingY = y * regionHeight;
const cv::Rect subArea = cv::Rect(startingX, startingY, regionWidth, regionHeight); const cv::Rect subArea = cv::Rect(startingX, startingY, regionWidth, regionHeight);
cv::Mat subBackground = m_background(subArea); cv::Mat subBackground = m_background(subArea);
cv::Mat subImage = image.getMat()(subArea); cv::Mat subImage = image.getMat()(subArea);
cv::Mat subResults = fgmask.getMat()(subArea); cv::Mat subResults = fgmaskmat(subArea);
subResults = (subBackground - subImage); subResults = (subBackground - subImage);
subBackground = (1.0 - learningRate) * subBackground + learningRate * subImage; subBackground = (1.0 - learningRate) * subBackground + learningRate * subImage;
...@@ -50,4 +59,8 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgm ...@@ -50,4 +59,8 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgm
for (const auto & asyncResult : merger) { for (const auto & asyncResult : merger) {
asyncResult.wait(); asyncResult.wait();
} }
if (fgmaskmat.data) {
cv::threshold(fgmaskmat, fgmaskmat, m_binarizationThreshold, 255, cv::THRESH_BINARY);
}
} }
...@@ -9,6 +9,10 @@ public: ...@@ -9,6 +9,10 @@ public:
void getBackgroundImage(cv::OutputArray backgroundImage) const override; void getBackgroundImage(cv::OutputArray backgroundImage) const override;
void setBinarizationThreshold(int value);
private: private:
cv::Mat m_background; cv::Mat m_background;
int m_binarizationThreshold;
}; };
...@@ -40,7 +40,7 @@ void ImagePreProcessor::init() ...@@ -40,7 +40,7 @@ void ImagePreProcessor::init()
QMutexLocker locker(&bgsMutex); QMutexLocker locker(&bgsMutex);
m_backgroundImage = std::make_shared<cv::Mat>(); m_backgroundImage = std::make_shared<cv::Mat>();
m_foregroundImage = std::make_shared<cv::Mat>(); m_foregroundMask = std::make_shared<cv::Mat>();
_backgroundSubtractionEnabled = true; _backgroundSubtractionEnabled = true;
_backgroundEnabled = true; _backgroundEnabled = true;
...@@ -51,21 +51,6 @@ void ImagePreProcessor::init() ...@@ -51,21 +51,6 @@ void ImagePreProcessor::init()
_resetBackgroundImageEnabled = false; _resetBackgroundImageEnabled = false;
} }
cv::Mat ImagePreProcessor::binarize(cv::Mat& image)
{
cv::Mat binarizedImage;
if (image.channels() >= 3)
cv::cvtColor(image, binarizedImage, cv::COLOR_BGR2GRAY);
else
image.copyTo(binarizedImage);
if (binarizedImage.data)
cv::threshold(binarizedImage, binarizedImage, m_TrackingParameter->getBinarizationThreshold(), 255, cv::THRESH_BINARY);
return binarizedImage;
}
cv::Mat ImagePreProcessor::erode(cv::Mat& image) cv::Mat ImagePreProcessor::erode(cv::Mat& image)
{ {
cv::Mat erodedImage; cv::Mat erodedImage;
...@@ -102,38 +87,37 @@ cv::Mat ImagePreProcessor::dilate(cv::Mat& image) ...@@ -102,38 +87,37 @@ cv::Mat ImagePreProcessor::dilate(cv::Mat& image)
cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image)
{ {
cv::Mat foreground; if (auto subtractor = dynamic_cast<CustomBackgroundSubtractor*>(m_subtractor); subtractor) {
m_subtractor->apply(image, foreground, m_TrackingParameter->getBackgroundRatio()); subtractor->setBinarizationThreshold(m_TrackingParameter->getBinarizationThreshold());
}
cv::Mat fgmask;
m_subtractor->apply(image, fgmask, m_TrackingParameter->getLearningRate());
m_subtractor->getBackgroundImage(*m_backgroundImage); m_subtractor->getBackgroundImage(*m_backgroundImage);
return foreground; return fgmask;
} }
std::map<std::string, std::shared_ptr<cv::Mat>> ImagePreProcessor::preProcess(std::shared_ptr<cv::Mat> p_image) std::map<std::string, std::shared_ptr<cv::Mat>> ImagePreProcessor::preProcess(std::shared_ptr<cv::Mat> p_image)
{ {
std::shared_ptr<cv::Mat> greyMat = std::make_shared<cv::Mat>(); std::shared_ptr<cv::Mat> greyMat = std::make_shared<cv::Mat>();
std::shared_ptr<cv::Mat> binarizedImage = std::make_shared<cv::Mat>();
std::shared_ptr<cv::Mat> erodedImage = std::make_shared<cv::Mat>(); std::shared_ptr<cv::Mat> erodedImage = std::make_shared<cv::Mat>();
std::shared_ptr<cv::Mat> dilatedImage = std::make_shared<cv::Mat>(); std::shared_ptr<cv::Mat> dilatedImage = std::make_shared<cv::Mat>();
cv::cvtColor(*p_image, *greyMat, cv::COLOR_BGR2GRAY); cv::cvtColor(*p_image, *greyMat, cv::COLOR_BGR2GRAY);
// 1. step: do the background subtraction // 1. step: do the background subtraction
*m_foregroundImage = backgroundSubtraction(*greyMat); *m_foregroundMask = backgroundSubtraction(*greyMat);
// 2. step: binarize the image
*binarizedImage = binarize(*m_foregroundImage);
// 3. step: erode the image // 2. step: erode the image
*erodedImage = erode(*binarizedImage); *erodedImage = erode(*m_foregroundMask);
// 4. step: dilate the image // 3. step: dilate the image
*dilatedImage = dilate(*erodedImage); *dilatedImage = dilate(*erodedImage);
std::map<std::string, std::shared_ptr<cv::Mat>> all; std::map<std::string, std::shared_ptr<cv::Mat>> all;
all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Greyscale"), greyMat)); all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Greyscale"), greyMat));
all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Background"), m_backgroundImage)); all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Background"), m_backgroundImage));
all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Foreground"), m_foregroundImage)); all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Foreground Mask"), m_foregroundMask));
all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Binarized"), binarizedImage));
all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Eroded"), erodedImage)); all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Eroded"), erodedImage));
all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Dilated"), dilatedImage)); all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Dilated"), dilatedImage));
......
...@@ -28,13 +28,6 @@ public: ...@@ -28,13 +28,6 @@ public:
*/ */
void init(); void init();
/**
* A computer vision method to binarize an image.
* @param: image, image to binarize,
* @return: a binarized image.
*/
cv::Mat binarize(cv::Mat& image);
/** /**
* A mathematical morphology operation using in computer vision to erode an image. * A mathematical morphology operation using in computer vision to erode an image.
* Erode image with 3x3 4-connectivity. * Erode image with 3x3 4-connectivity.
...@@ -82,7 +75,7 @@ private: ...@@ -82,7 +75,7 @@ private:
cv::Mat _outputImage; cv::Mat _outputImage;
std::shared_ptr<cv::Mat> m_backgroundImage; std::shared_ptr<cv::Mat> m_backgroundImage;
std::shared_ptr<cv::Mat> m_foregroundImage; std::shared_ptr<cv::Mat> m_foregroundMask;
//parameters for image pre-processing //parameters for image pre-processing
bool _backgroundSubtractionEnabled; bool _backgroundSubtractionEnabled;
......
...@@ -26,7 +26,7 @@ TrackerParameterView::TrackerParameterView(QWidget *parent, IController *control ...@@ -26,7 +26,7 @@ TrackerParameterView::TrackerParameterView(QWidget *parent, IController *control
connect(_ui->lineEdit_9MaxBlob, qOverload<int>(&QSpinBox::valueChanged), parameter, &TrackerParameter::setMaxBlobSize); connect(_ui->lineEdit_9MaxBlob, qOverload<int>(&QSpinBox::valueChanged), parameter, &TrackerParameter::setMaxBlobSize);
connect(_ui->lineEdit_9MaxBlob, qOverload<int>(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); connect(_ui->lineEdit_9MaxBlob, qOverload<int>(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged);
connect(_ui->lineEdit_7_learningRate, qOverload<double>(&QDoubleSpinBox::valueChanged), parameter, &TrackerParameter::setBackgroundRatio); connect(_ui->lineEdit_7_learningRate, qOverload<double>(&QDoubleSpinBox::valueChanged), parameter, &TrackerParameter::setLearningRate);
connect(_ui->lineEdit_7_learningRate, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); connect(_ui->lineEdit_7_learningRate, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged);
} }
...@@ -61,7 +61,7 @@ void TrackerParameterView::getNotified() ...@@ -61,7 +61,7 @@ void TrackerParameterView::getNotified()
val = parameter->getSizeDilate(); val = parameter->getSizeDilate();
_ui->lineEdit_4_SizeDilate->setValue(val); _ui->lineEdit_4_SizeDilate->setValue(val);
double dval = parameter->getBackgroundRatio(); double dval = parameter->getLearningRate();
_ui->lineEdit_7_learningRate->setValue(dval); _ui->lineEdit_7_learningRate->setValue(dval);
val = parameter->getMinBlobSize(); val = parameter->getMinBlobSize();
......
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property> </property>
<property name="horizontalSpacing"> <property name="horizontalSpacing">
<number>44</number> <number>13</number>
</property> </property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="label_7">
...@@ -103,6 +103,26 @@ ...@@ -103,6 +103,26 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Binarization Threshold:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="lineEdit_2_binThresh">
<property name="minimumSize">
<size>
<width>132</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>Set the binarization threshold</string>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QDoubleSpinBox" name="lineEdit_7_learningRate"> <widget class="QDoubleSpinBox" name="lineEdit_7_learningRate">
<property name="minimumSize"> <property name="minimumSize">
...@@ -188,36 +208,16 @@ ...@@ -188,36 +208,16 @@
<enum>QFormLayout::ExpandingFieldsGrow</enum> <enum>QFormLayout::ExpandingFieldsGrow</enum>
</property> </property>
<property name="horizontalSpacing"> <property name="horizontalSpacing">
<number>16</number> <number>74</number>
</property> </property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Binarization Threshold:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="lineEdit_2_binThresh">
<property name="minimumSize">
<size>
<width>132</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>Set the binarization threshold</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>Size Erosion:</string> <string>Size Erosion:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="0" column="1">
<widget class="QSpinBox" name="lineEdit_3_SizeErode"> <widget class="QSpinBox" name="lineEdit_3_SizeErode">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
...@@ -230,14 +230,14 @@ ...@@ -230,14 +230,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>Size Dilation:</string> <string>Size Dilation:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="1" column="1">
<widget class="QSpinBox" name="lineEdit_4_SizeDilate"> <widget class="QSpinBox" name="lineEdit_4_SizeDilate">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
...@@ -364,12 +364,7 @@ ...@@ -364,12 +364,7 @@
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Foreground</string> <string>Foreground Mask</string>
</property>
</item>
<item>
<property name="text">
<string>Binarized</string>
</property> </property>
</item> </item>
<item> <item>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment