简单地说,这是一个可用的输入和相应的输出的例子:
In: [ 0 0 0 0 0 0 1 0 1 0
0 6 6 0 0 0 0 1 1 0
0 8 9 0 0 0 0 0 1 1
8 0 0 0 9 9 0 0 0 0
0 0 0 0 8 8 0 0 0 0
0 0 0 0 0 0 0 0 0 0
9 9 7 0 0 0 0 0 1 0
0 6 8 0 0 0 0 3 2 0
0 0 0 0 0 0 0 2 1 0
0 0 0 0 0 0 0 0 0 0 ]二值化后用cv2.connectedComponents()获取标记图像
labels: [ 0 0 0 0 0 0 1 0 1 0
0 2 2 0 0 0 0 1 1 0
0 2 2 0 0 0 0 0 1 1
2 0 0 0 3 3 0 0 0 0
0 0 0 0 3 3 0 0 0 0
0 0 0 0 0 0 0 0 0 0
4 4 4 0 0 0 0 0 5 0
0 4 4 0 0 0 0 5 5 0
0 0 0 0 0 0 0 5 5 0
0 0 0 0 0 0 0 0 0 0 ]从这里开始,我希望得到以下输出:
Out: [0 0 0 0 0 0 0 0 0 0
0 6 6 0 0 0 0 0 0 0
0 8 9 0 0 0 0 0 0 0
8 0 0 0 9 9 0 0 0 0
0 0 0 0 8 8 0 0 0 0
0 0 0 0 0 0 0 0 0 0
9 9 7 0 0 0 0 0 0 0
0 6 8 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 ]有许多连接的组件存在(在本例中:5个8-连接组件)。(中的中的)像素之和< 10 (一个阈值)的组件在Out中删除。
如何在C++ (可能使用OpenCV)中实现这一点?
我已经在Python上使用OpenCV完成了它,但是无法在C++上实现。
这是我的Python代码的一部分,如果有用的话( cv2.connectedComponents()的输出是标签 ):
for cnt in range(1, labels.max()+1):
idx = np.where(labels.copy() == cnt)
valMat = In[idx]
sum_valMat = sum(valMat)
if sum_valMat > 3000:
fingerNodes[idx] = 0输入是一个简单的二维矩阵。这是一个连接组件的示例:

发布于 2018-02-08 05:12:21
您已经在Python中实现了这一点,所以您知道如何解决这个问题。我想,能够在C++中实现它是一个了解您想要使用的库的问题。
您的Python实现效率很低:遍历标签,对于每个标签访问每个图像像素(idx = np.where(labels.copy() == cnt))。如果你有更多的标签,这会变得非常昂贵。
在下面的代码中,我循环遍历图像一次以累积每个标签的图像强度之和,然后一次用计算的和绘制图像(对于带有标签的每个像素,查找该标签的和),然后再一次对该图像进行阈值处理。然后,我使用这个阈值图像作为掩码,将输入图像中不想保留的像素设置为0。
我这里用DIPlib。不过,如果您真的想使用OpenCV,我相信您可以以某种方式复制它。
#include "diplib.h"
#include "dipviewer.h"
#include "diplib/file_io.h"
#include "diplib/regions.h"
#include "diplib/measurement.h"
int main() {
// Create a test image with similar properties to your example
dip::Image input = -dip::ImageReadICS( "/Users/cris/newdip/examples/cermet.ics" );
input.At( input < 120 ) = 0;
// Display
dip::viewer::ShowSimple( input, "input image" );
// Threshold and label
dip::Image label = dip::Label( input > 0 );
// Obtain sum of pixels per label
dip::MeasurementTool measurementTool;
auto msr = measurementTool.Measure( label, input, { "Mass" } );
// Paint each label with the measured value
dip::Image feature = dip::ObjectToMeasurement( label, msr[ "Mass" ] );
// Create output as a copy of the input, with low feature values set to 0
dip::Image output = input.Copy();
output.At( feature < 100000 ) = 0;
// Display
dip::viewer::ShowSimple( output, "output image" );
dip::viewer::Spin();
}

发布于 2018-03-01 20:27:16
如果您想继续使用opencv,您可以使用cv::calcHist来计算每个标签的出现次数,以及对应于小于10的bin值的filrerout值。然后,应该对产生的标签图像进行二值化,并按元素顺序乘以源,以获得所需的结果。
https://stackoverflow.com/questions/48669181
复制相似问题