【问题标题】:Recognizing a topological graph in a noisy image识别嘈杂图像中的拓扑图
【发布时间】:2014-06-01 01:03:34
【问题描述】:

我对机器学习或图像处理完全没有经验,所以我希望有人可以就这个问题给出一些初步的想法:

下图是番茄植物叶子的照片示例。我们有成千上万的这些。我们需要追踪静脉并输出图形。我们已经让数百名本科生手动追踪静脉,所以我认为这可以作为机器学习方法的训练集。

所以我的问题是:立即想到哪些类型的过滤器/分类器?你有什么推荐我阅读或看看的吗?

我们的第一个想法是,看看方向导数。每个像素可以被分类为在给定角度处于边缘或不在边缘,如果一个像素在许多不同的角度处于一个边缘,那么它可能是一个斑点而不是一个静脉。然后可以通过学习调整梯度阈值和允许的角度变化的参数,但这可能不是最好的方法......

感谢您的帮助!

【问题讨论】:

  • 这个问题看起来很有趣,如果您在原型设计/实施解决方案方面需要帮助,请告诉我

标签: image-processing machine-learning graph-theory topology


【解决方案1】:

立即想到两种方法

  1. 滑动窗口神经网络分类器
  2. 识别用于区分图像中暗/亮像素的阈值(这可以使用机器学习或简单的计算来完成),然后进行填充以识别图像中的区域。

第二种方法应该更简单更快,所以我可能会先对其进行原型设计,看看它是否给出了足够好的答案。

无论如何,我的直觉是解决对偶问题会更容易——不是试图找到图的边和节点,而是找到它的面。由此,您可以轻松获得图表本身。

【讨论】:

  • 感谢您指出对偶问题会更容易——消除点和平滑噪声比自己找到边缘更容易处理!
【解决方案2】:

我做了这个非常简单的程序来使用 opencv 过滤静脉区域。我添加了 cmets 来解释操作。保存中间步骤的结果图像。希望对您有所帮助。

#include "stdafx.h"

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;

#define INPUT_FILE              "wMTjH3L.png"
#define OUTPUT_FOLDER_PATH      string("")
#define CONTOUR_AREA_THRESHOLD  30.0

int _tmain(int argc, _TCHAR* argv[])
{
    // read image as grayscale
    Mat im = imread(INPUT_FILE, CV_LOAD_IMAGE_GRAYSCALE);
    imwrite(OUTPUT_FOLDER_PATH + string("gray.jpg"), im);
    // smooth the image with a gaussian filter
    Mat blurred;
    GaussianBlur(im, blurred, Size(3, 3), 1.5);
    imwrite(OUTPUT_FOLDER_PATH + string("blurred.jpg"), blurred);
    // flatten lighter regions while retaining the darker vein regions using morphological opening
    Mat morph;
    Mat morphKernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
    morphologyEx(blurred, morph, MORPH_OPEN, morphKernel);
    imwrite(OUTPUT_FOLDER_PATH + string("morph.jpg"), morph);
    // apply adaptive thresholding
    Mat adaptTh;
    adaptiveThreshold(morph, adaptTh, 255.0, ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, 7, 2.0);
    imwrite(OUTPUT_FOLDER_PATH + string("adaptth.jpg"), adaptTh);
    // morphological closing to merge disjoint regions
    Mat morphBin;
    Mat morphKernelBin = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
    morphologyEx(adaptTh, morphBin, MORPH_CLOSE, morphKernelBin);
    imwrite(OUTPUT_FOLDER_PATH + string("adptmorph.jpg"), morphBin);
    // find contours
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(morphBin, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
    // filter contours by region areas and draw
    RNG rng(12345);
    Mat drawing = Mat::zeros(morphBin.size(), CV_8UC3);
    for(int idx = 0; idx >= 0; idx = hierarchy[idx][0])
    {
         if (contourArea(contours[idx]) > CONTOUR_AREA_THRESHOLD)
         {
             Scalar color( rand()&255, rand()&255, rand()&255 );
             drawContours( drawing, contours, idx, color, CV_FILLED, 8, hierarchy );
         }
    }
    imwrite(OUTPUT_FOLDER_PATH + string("cont.jpg"), drawing);
    return 0;
}

提供的示例图像的输出如下所示:

【讨论】:

  • 您好,感谢您这样做!这看起来很有希望,需要对参数进行一些调整。这是一个非常简单的解决方案,我一定会及时通知您该项目的最新情况,尤其是在我们严重依赖此方法的情况下。
猜你喜欢
  • 1970-01-01
  • 2014-04-03
  • 2011-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多