使用OpenCV去除二进制图像中的噪声

8

我使用openCV将视频读入到Visual Studio中,并将其转换为灰度图像,然后使用函数CV_THRESH_BINARY将其转换为二进制图像。然而,帧中存在空洞和噪音。有没有简单的方法来消除这些噪音或空洞?我已经研究了openCV中的腐蚀和膨胀函数,但我并不太清楚如何使用它们。以下是我的代码。如果有人能向我展示如何将去噪过程纳入我的代码中,那将不胜感激。

#include "cv.h"
#include "highgui.h"

int main( int argc, char* argv ) {

CvCapture *capture = NULL;
capture = cvCaptureFromAVI("C:\\walking\\lady walking.avi");
if(!capture){
    return -1;
}

IplImage* color_frame = NULL;
IplImage* gray_frame = NULL ;
int thresh_frame = 70;

int frameCount=0;//Counts every 5 frames
cvNamedWindow( "Binary video", CV_WINDOW_AUTOSIZE );

while(1) {
    color_frame = cvQueryFrame( capture );//Grabs the frame from a file
    if( !color_frame ) break;
    gray_frame = cvCreateImage(cvSize(color_frame->width, color_frame->height),      color_frame->depth, 1);
    if( !color_frame ) break;// If the frame does not exist, quit the loop

    frameCount++;
    if(frameCount==5)
    {
        cvCvtColor(color_frame, gray_frame, CV_BGR2GRAY);
        cvThreshold(gray_frame, gray_frame, thresh_frame, 255, CV_THRESH_BINARY);
        cvShowImage("Binary video", gray_frame);
        frameCount=0;
    }
    char c = cvWaitKey(33);
    if( c == 27 ) break;
}

cvReleaseImage(&color_frame);
cvReleaseImage(&gray_frame);
cvReleaseCapture( &capture );
cvDestroyWindow( "Grayscale video" );

return 0;
}
2个回答

10

免责声明:由于您提供的信息非常少,因此很难给出一个好的答案。如果您在二值化之前和之后发布了图像,那么这将更容易。但是,我会尝试给出一些提示。

如果孔比较大,则可能阈值设置不正确,请尝试增加或减小它并检查结果。您可以尝试

cv::threshold(gray_frame, gray_frame, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

这将自动计算阈值。 如果您找不到一个好的阈值,那么可以尝试一些自适应阈值算法,opencv有adaptiveThreshold()函数,但它并不是很好。
如果孔和噪声相当小(每个几个像素),您可以尝试以下一些方法:
- 使用开运算(腐蚀,下一个膨胀)来去除白色噪声和闭运算(膨胀,下一个腐蚀)来去除小黑噪声。但要记住,开运算虽然可以去除白色噪声,但也会加强黑色噪声,反之亦然。 - 在二值化后使用中值模糊。它可以去除小噪声(黑色和白色),同时保留颜色(图像仍将是二进制的),并且可能会有小错误,形状不变。在二值化之前应用中值模糊也有助于减少小噪声。

非常抱歉没有提供图片,但是非常感谢您的帮助。我使用了cvErode函数来移除图像中的某些孔洞,但是我也会尝试中值模糊。当您提到使用开运算和闭运算时,我必须同时使用它们还是只使用CV_MOP_OPEN或CV_MOP_CLOSE其中之一? - sue-ling
你仍然可以提供它们 :) 你可以使用其中之一或两个,依次使用,这取决于你想要实现什么。只需检查结果并进行实验。 - Tomasz Niedabylski
我检查了结果并决定使用Erode和Dilate函数可以获得更好的结果,所以我会依次使用它们。无论如何,由于我是stackoverflow的新手,我不知道如何提供图片:/非常抱歉。我目前正在进行一个涉及C++和openCV的图像处理项目。它基于运动识别,所以如果我发布更多问题,如果您能提供一些帮助,我将不胜感激。谢谢:) - sue-ling
你能否帮我点赞?这样我才能获得超过10个声望分数。我想要在这个问题https://dev59.com/2WDVa4cB1Zd3GeqPfqoa上发布图片,但需要更高的声望分数,而我现在只有10个声望分数。如果您能帮忙回答这个问题,那就太好了 :) - sue-ling

1

在进行阈值处理之前,您可以尝试使用Smooth函数和CV_MEDIAN


这样做能够达到与腐蚀和膨胀函数相同的结果吗?你熟悉这些函数的使用吗? - sue-ling
你可以使用开闭运算(腐蚀+膨胀或反之),显然你需要调整核大小。 - andrea
@andrea,你能帮我解决这个问题吗?https://dev59.com/2WDVa4cB1Zd3GeqPfqoa - sue-ling
在我的应用程序中,我使用了开运算和闭运算两种操作。这两个函数的核心是相同的。通过这种方式,您可以消除(或大大减少)盐和胡椒噪声以及比盐和胡椒更大的孔洞。正如我所说,内核的大小取决于噪声斑点的大小和您正在跟踪的对象的大小。 - andrea
请查看以下网址:http://homepages.inf.ed.ac.uk/rbf/HIPR2/close.htm 和 http://homepages.inf.ed.ac.uk/rbf/HIPR2/open.htm。 - andrea
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接