【问题标题】:Image Segmentation - Remove Unwanted Pixels in C++图像分割 - 在 C++ 中删除不需要的像素
【发布时间】:2018-09-10 06:57:22
【问题描述】:

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

#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,但我无法实现。由于链码,它非常重要。

【问题讨论】:

  • cv::findContours 不是已经给了你一个轮廓列表,其中每个的大小描述了轮廓的长度吗?如果是单个像素外的 8 连接,则由四个元素组成。或者只是变形关闭或使用连接组件标签预先填充孔。
  • 我试过了,但它没有用,或者我不能用它。我使用了 morph close 但结果仍然相同。
  • 也许您可以发布您希望实现的图像?但是在阈值之后对二值图像使用cv::findContours,这里不需要边缘检测器。
  • @mainactual 好的,我在帖子上进行了编辑。你可以检查一下。

标签: c++ opencv image-processing image-segmentation


【解决方案1】:

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

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

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

2i & 2ii) 如果是手工标注,可以继续手工采集轮廓向量,也可以切换到cv::findContours

希望对你有帮助

【讨论】:

    猜你喜欢
    • 2020-03-31
    • 2011-02-18
    • 1970-01-01
    • 2015-06-23
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多