mirror of
https://github.com/opencv/opencv.git
synced 2025-06-11 03:33:28 +08:00
fix #26138: Saturation between single and multi-channel matrix operation
Description: The issue was that when doing the operation m = c*(m - b) with m being an 8-Bit 3-channel matrix (CV_8UC3), the result of c*(m-b) should be a matrix with values of 4*(100-70)=120. Instead, it is a matrix of zeros because 4*100 was capped at 255 and after subtracting 4*70 we get -25 which becomes 0 after the final saturation operation. So instead I am performing calculations in higher precision (CV_16S or CV_32F) to prevent capping out at 255 during the operations and after performing the operation I convert it back to the original type ensuring that capping at 255 happens only once.
This commit is contained in:
parent
57a78cb9df
commit
05dd290e15
@ -1341,8 +1341,13 @@ void MatOp_AddEx::assign(const MatExpr& e, Mat& m, int _type) const
|
||||
cv::subtract(e.s, e.a, dst);
|
||||
else
|
||||
{
|
||||
e.a.convertTo(dst, e.a.type(), e.alpha);
|
||||
cv::add(dst, e.s, dst);
|
||||
int depth = e.a.depth();
|
||||
int precType = (depth == CV_8U || depth == CV_16U) ? CV_16S : CV_32F;
|
||||
cv::Mat prec;
|
||||
e.a.convertTo(prec, precType);
|
||||
prec = prec * e.alpha;
|
||||
cv::add(prec, e.s, prec);
|
||||
prec.convertTo(dst, e.a.type());
|
||||
}
|
||||
|
||||
if( dst.data != m.data )
|
||||
|
@ -2634,4 +2634,29 @@ TEST(Mat, Recreate1DMatWithSameMeta)
|
||||
EXPECT_NO_THROW(m.create(dims, depth));
|
||||
}
|
||||
|
||||
TEST(Mat, ScalarMultiplicationSaturation) {
|
||||
for (int c = 1; c <= 9; c++) {
|
||||
cv::Mat m1 = cv::Mat::zeros(1,1, CV_8UC1);
|
||||
cv::Mat m3 = cv::Mat::zeros(1,1, CV_8UC3);
|
||||
m1 += cv::Scalar(100);
|
||||
m3 += cv::Scalar(100,100,100);
|
||||
cv::Scalar b1 = cv::Scalar(70);
|
||||
cv::Scalar b3 = cv::Scalar(70,70,70);
|
||||
m1 = c * (m1 - b1);
|
||||
m3 = c * (m3 - b3);
|
||||
int m1_val = m1.at<uchar>(0,0);
|
||||
int m3_val = m3.at<cv::Vec3b>(0,0)[0];
|
||||
|
||||
if (c * (100 - 70) > 255) {
|
||||
EXPECT_EQ(m1_val, 255);
|
||||
} else {
|
||||
EXPECT_EQ(m1_val, c * (100 - 70));
|
||||
}
|
||||
if (c * (100 - 70) > 255) {
|
||||
EXPECT_EQ(m3_val, 255);
|
||||
} else {
|
||||
EXPECT_EQ(m3_val, c * (100 - 70));
|
||||
}
|
||||
}
|
||||
}
|
||||
}} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user