图像分割 - 在 C++ 中删除不需要的像素

Image Segmentation - Remove Unwanted Pixels in C++

我从事图像处理工作。首先,我必须进行图像分割并只提取图像的边界。然后,将此图像转换为弗里曼链码。 freeman 链码部分没问题。但是,当我对图像进行分割时,图像内部仍然存在一些不需要的白色像素。因此,下一步,即弗里曼链码,并没有成功。我的意思是,由于不需要的像素,它给出了不正确的链码。所以,我必须从图像内部删除不需要的像素。我会分享我的代码,你能告诉我如何更改这段代码,或者我应该为这个过滤器编写什么样的正确代码?代码在这里:

#include <opencv2/opencv.hpp>
#include <vector>
#include <iostream>
#include <opencv2/imgproc/imgproc_c.h>
using namespace cv;
using namespace std;
int main(){
    Mat img = imread("<image-path>");
    Mat gray;
    cvtColor(img,gray,CV_BGR2GRAY);
    Mat binary;
    threshold(gray,binary, 200, 255, CV_THRESH_BINARY);
    Mat kernel = (Mat_<float>(3,3) <<
            1, 1, 1,
            1, -8, 1,
            1, 1, 1);
    Mat imgLaplacian;
    Mat sharp= binary;
    filter2D(binary, imgLaplacian, CV_32F, kernel);
    binary.convertTo(sharp, CV_32F);
    Mat imgResult = sharp - imgLaplacian;
    imgResult.convertTo(imgResult, CV_8UC1);
    imgLaplacian.convertTo(imgLaplacian, CV_8UC1);
    //Find contours
    vector<vector<Point>> contours;
    vector <uchar> chaincode;
    vector <char> relative;
    findContours(imgLaplacian,contours, CV_RETR_LIST, CHAIN_APPROX_NONE);
    for (size_t i=0; i<contours.size();i++){
        chain_freeman(contours[i],chaincode);
        FileStorage fs("<file-path>", 1);
        fs << "chain" << chaincode;
    }
    for (size_t i=0; i<chaincode.size()-1; i++){
        int relative1 = 0;
        relative1 = abs(chaincode[i]-chaincode[i+1]);
        cout << relative1;
        for (int j=0; j<relative1; j++){
        }
        relative.push_back(relative1);
            FileStorage fs("<file-path>", 1);
            fs << "chain" << relative;
        }


    imshow("binary",imgLaplacian);
    cvWaitKey();
        return 0;
}

original image

Result

在这个结果中,我想删除图像内部的白色像素。我在 opencv 中尝试了所有 fiter,但我无法实现。因为有链码所以很重要

好的,现在我明白了。如前所述,您可以简单地根据长度忽略小轮廓。对于其余部分,您需要最细的轮廓(似乎是 4-connected 的情况)。你有几个选择:

1) 电流变细。如果您可以获取 Matlab 的查找 table,则可以将其作为 How to use Matlab's 512 element lookup table array in OpenCV?

加载到 OpenCV 中

2) 二值化后手工标记边界像素非常简单。为了提高效率,您可以先通过在背景上应用连接组件标记来填充小空腔(小岛)(这次使用相反的连接,它是 8)。

2i & 2ii) 如果手工标注,可以继续手工采集等高线向量或者切换到cv::findContours

希望对您有所帮助