1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge pull request #18624 from qchateau:similarity-mask

* support similarity masks

* add test for similarity threshold

* short license in test

* use UMat in buildSimilarityMask

* fix win32 warnings

* fix test indentation

* fix umat/mat sync

* no in-place argument for erode/dilate
This commit is contained in:
Quentin Chateau
2020-10-22 14:24:58 +02:00
committed by GitHub
parent 3a99fb9d34
commit ea1e3fb90d
4 changed files with 187 additions and 4 deletions
+98 -1
View File
@@ -90,6 +90,7 @@ void GainCompensator::feed(const std::vector<Point> &corners, const std::vector<
const int num_images = static_cast<int>(images.size());
Mat accumulated_gains;
prepareSimilarityMask(corners, images);
for (int n = 0; n < nr_feeds_; ++n)
{
@@ -133,6 +134,8 @@ void GainCompensator::singleFeed(const std::vector<Point> &corners, const std::v
Mat subimg1, subimg2;
Mat_<uchar> submask1, submask2, intersect;
std::vector<UMat>::iterator similarity_it = similarities_.begin();
for (int i = 0; i < num_images; ++i)
{
for (int j = i; j < num_images; ++j)
@@ -147,6 +150,13 @@ void GainCompensator::singleFeed(const std::vector<Point> &corners, const std::v
submask2 = masks[j].first(Rect(roi.tl() - corners[j], roi.br() - corners[j])).getMat(ACCESS_READ);
intersect = (submask1 == masks[i].second) & (submask2 == masks[j].second);
if (!similarities_.empty())
{
CV_Assert(similarity_it != similarities_.end());
UMat similarity = *similarity_it++;
bitwise_and(intersect, similarity, intersect);
}
int intersect_count = countNonZero(intersect);
N(i, j) = N(j, i) = std::max(1, intersect_count);
@@ -298,6 +308,88 @@ void GainCompensator::setMatGains(std::vector<Mat>& umv)
}
}
void GainCompensator::prepareSimilarityMask(
const std::vector<Point> &corners, const std::vector<UMat> &images)
{
if (similarity_threshold_ >= 1)
{
LOGLN(" skipping similarity mask: disabled");
return;
}
if (!similarities_.empty())
{
LOGLN(" skipping similarity mask: already set");
return;
}
LOGLN(" calculating similarity mask");
const int num_images = static_cast<int>(images.size());
for (int i = 0; i < num_images; ++i)
{
for (int j = i; j < num_images; ++j)
{
Rect roi;
if (overlapRoi(corners[i], corners[j], images[i].size(), images[j].size(), roi))
{
UMat subimg1 = images[i](Rect(roi.tl() - corners[i], roi.br() - corners[i]));
UMat subimg2 = images[j](Rect(roi.tl() - corners[j], roi.br() - corners[j]));
UMat similarity = buildSimilarityMask(subimg1, subimg2);
similarities_.push_back(similarity);
}
}
}
}
UMat GainCompensator::buildSimilarityMask(InputArray src_array1, InputArray src_array2)
{
CV_Assert(src_array1.rows() == src_array2.rows() && src_array1.cols() == src_array2.cols());
CV_Assert(src_array1.type() == src_array2.type());
CV_Assert(src_array1.type() == CV_8UC3 || src_array1.type() == CV_8UC1);
Mat src1 = src_array1.getMat();
Mat src2 = src_array2.getMat();
UMat umat_similarity(src1.rows, src1.cols, CV_8UC1);
Mat similarity = umat_similarity.getMat(ACCESS_WRITE);
if (src1.channels() == 3)
{
for (int y = 0; y < similarity.rows; ++y)
{
for (int x = 0; x < similarity.cols; ++x)
{
Vec<float, 3> vec_diff =
Vec<float, 3>(*src1.ptr<Vec<uchar, 3>>(y, x))
- Vec<float, 3>(*src2.ptr<Vec<uchar, 3>>(y, x));
double diff = norm(vec_diff * (1.f / 255.f));
*similarity.ptr<uchar>(y, x) = diff <= similarity_threshold_ ? 255 : 0;
}
}
}
else // if (src1.channels() == 1)
{
for (int y = 0; y < similarity.rows; ++y)
{
for (int x = 0; x < similarity.cols; ++x)
{
float diff = std::abs(static_cast<int>(*src1.ptr<uchar>(y, x))
- static_cast<int>(*src2.ptr<uchar>(y, x))) / 255.f;
*similarity.ptr<uchar>(y, x) = diff <= similarity_threshold_ ? 255 : 0;
}
}
}
similarity.release();
Mat kernel = getStructuringElement(MORPH_RECT, Size(3,3));
UMat umat_erode;
erode(umat_similarity, umat_erode, kernel);
dilate(umat_erode, umat_similarity, kernel);
return umat_similarity;
}
void ChannelsCompensator::feed(const std::vector<Point> &corners, const std::vector<UMat> &images,
const std::vector<std::pair<UMat,uchar> > &masks)
{
@@ -317,11 +409,15 @@ void ChannelsCompensator::feed(const std::vector<Point> &corners, const std::vec
// For each channel, feed the channel of each image in a GainCompensator
gains_.clear();
gains_.resize(images.size());
GainCompensator compensator(getNrFeeds());
compensator.setSimilarityThreshold(getSimilarityThreshold());
compensator.prepareSimilarityMask(corners, images);
for (int c = 0; c < 3; ++c)
{
const std::vector<UMat>& channels = images_channels[c];
GainCompensator compensator(getNrFeeds());
compensator.feed(corners, channels, masks);
std::vector<double> gains = compensator.gains();
@@ -400,6 +496,7 @@ void BlocksCompensator::feed(const std::vector<Point> &corners, const std::vecto
{
Compensator compensator;
compensator.setNrFeeds(getNrFeeds());
compensator.setSimilarityThreshold(getSimilarityThreshold());
compensator.feed(block_corners, block_images, block_masks);
gain_maps_.clear();