我正在用Python和C++实现MATLAB的imreconstruct
.然而,对于我的测试用例,Python实现与MATLAB的输出匹配,而C++则不匹配.
以下是Python的实现:
def imReconstruct(marker: np.array, mask: np.array) -> np.array:
"""
Naive implementation of MatLAB's imReconstruct function
works when `mask` consists of mostly background (global minumum)
will be slow otherwise
"""
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
# calculate the extreme values of the mask image
min_val, max_val, _, _ = cv.minMaxLoc(mask)
# clip the marker by global extrema of mask
_, marker = cv.threshold(marker, min_val, max_val, cv.THRESH_TRUNC | cv.THRESH_BINARY_INV)
while True:
expanded = cv.dilate(marker, kernel)
expanded = np.minimum(expanded, mask)
# return `expanded` when the difference is small
if np.max(np.abs(expanded - marker)) < 1e-5:
return expanded
# set expanded to marker and repeat
marker = expanded
D = np.array(
[[4.2426405, 3.6055512, 3.1622777, 3. , 3. ],
[3.6055512, 2.828427 , 2.236068 , 2. , 2. ],
[3.1622777, 2.236068 , 1.4142135, 1. , 1. ],
[3. , 2. , 1. , 0. , 0. ],
[3. , 2. , 1. , 0. , 0. ]], dtype=float32)
imReconstruct(D-.85,D)
# output
# array([[3.3926406, 3.3926406, 3.1622777, 3. , 3. ],
# [3.3926406, 2.828427 , 2.236068 , 2. , 2. ],
# [3.1622777, 2.236068 , 1.4142135, 1. , 1. ],
# [3. , 2. , 1. , 0. , 0. ],
# [3. , 2. , 1. , 0. , 0. ]], dtype=float32)
而C++:
Mat imReconstruct(Mat marker, Mat mask){
/**************
* naive implementation of MatLAB's imReconstruct
* works when `mask` consist of mostly background (global minimum)
* will be slow otherwise
*************/
Mat kernel = getStructuringElement(MORPH_RECT, Size(3,3));
// calculate the min and max values from mask
double minMask, maxMask;
minMaxLoc(mask, &minMask, &maxMask);
// clip the marker by global extrema of mask
threshold(marker, marker, minMask, maxMask, THRESH_TRUNC|THRESH_BINARY_INV);
Mat expanded;
// keep filling the holes with `dilate`
// until there are no more changes
while (1){
dilate(marker, expanded, kernel);
expanded = min(expanded, mask);
// compute the max difference
minMaxLoc(expanded-marker, &minMask, &maxMask);
// return image when changes are small
if (maxMask<1e-5) return expanded;
// set expanded as marker and continue looping
marker = expanded;
}
}
// test case
cv::Mat D = (cv::Mat_<float> (5,5) <<
4.2426405, 3.6055512, 3.1622777, 3. , 3. ,
3.6055512, 2.828427 , 2.236068 , 2. , 2. ,
3.1622777, 2.236068 , 1.4142135, 1. , 1. ,
3. , 2. , 1. , 0. , 0. ,
3. , 2. , 1. , 0. , 0.
);
std::cout << imReconstruct(D - .85, D) << std::endl;
// output
// [3.3926406, 3.3926406, 3.1622777, 2.7555513, 2.3122778;
// 3.3926406, 2.8284271, 2.236068, 2, 2;
// 3.1622777, 2.236068, 1.4142135, 1, 1;
// 2.7555513, 2, 1, 0, 0;
// 2.3122778, 2, 1, 0, 0]
造成这种差异的原因是什么?我可能忽略了一些简单的事情,但我已经花了几个小时徒劳,没有任何积极的结果.