是否有可能在 emgucv 中找到“斑点”区域的边缘?

2023-11-24

我有一个看起来像这样的图像:

original

我想找到黑暗部分的边缘,如下所示(红线是我正在寻找的):

required

我尝试了几种方法,但没有一个有效,所以我希望有一位 emgu 大师愿意帮助我......

方法一

  • 将图像转换为灰度
  • 去除噪音并反转
  • 删除任何不太亮的东西
  • 获取精明和多边形

代码(我知道我应该正确处理东西,但我保持代码简短):

var orig = new Image<Bgr, byte>(inFile);

var contours = orig
    .Convert<Gray, byte>()
    .PyrDown()
    .PyrUp()
    .Not()
    .InRange(new Gray(190), new Gray(255))
    .Canny(new Gray(190), new Gray(255))
    .FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
                  RETR_TYPE.CV_RETR_TREE);

var output = new Image<Gray, byte>(orig.Size);    
for (; contours != null; contours = contours.HNext)
{
    var poly = contours.ApproxPoly(contours.Perimeter*0.05,
                                   contours.Storage);
    output.Draw(poly, new Gray(255), 1);
}
output.Save(outFile);

这是结果:

approach 1 result

方法2

  • 将图像转换为灰度
  • 去除噪音并反转
  • 删除任何不太亮的东西
  • 得到精明的然后线条

代码:

var orig = new Image<Bgr, byte>(inFile);

var linesegs = orig
    .Convert<Gray, byte>()
    .PyrDown()
    .PyrUp()
    .Not()
    .InRange(new Gray(190), new Gray(255))
    .Canny(new Gray(190), new Gray(255))
    .HoughLinesBinary(
        1,
        Math.PI/45.0,
        20,
        30,
        10
    )[0];

var output = new Image<Gray, byte>(orig.Size);    
foreach (var l in linesegs)
{
    output.Draw(l, new Gray(255), 1);
}
output.Save(outFile);

这是结果:

approach 2 result

Notes

我尝试过调整这两种方法的所有参数并添加平滑,但我永远无法获得我需要的简单边缘,因为我认为较暗的区域不是纯色。

我也尝试过膨胀和腐蚀,但是我必须输入的参数太高才能获得单一颜色,以至于我最终在右侧包含了一些灰色的东西并失去了准确性。


是的,有可能,具体方法如下:

  • 更改图像的对比度以使较亮的部分消失:

enter image description here

  • 然后,将其转换为HSV,对Saturation通道进行阈值操作:

enter image description here

  • 并执行侵蚀和膨胀操作以消除噪音:

enter image description here

此时您将获得您想要的结果。出于测试目的,最后我执行the 边界框展示如何检测感兴趣区域的起点和终点的技术:

enter image description here

我没有时间调整参数并进行完美的检测,但我相信你能弄清楚。这个答案提供了实现这一目标的路线图!

这是我编写的 C++ 代码,我相信您能够将其转换为 C#:

#include <cv.h>
#include <highgui.h>

int main(int argc, char* argv[])
{
    cv::Mat image = cv::imread(argv[1]);
    cv::Mat new_image = cv::Mat::zeros(image.size(), image.type());

    /* Change contrast: new_image(i,j) = alpha*image(i,j) + beta */

    double alpha = 1.8;     // [1.0-3.0]
    int beta = 100;         // [0-100]
    for (int y = 0; y < image.rows; y++)
    { 
        for (int x = 0; x < image.cols; x++)
        { 
        for (int c = 0; c < 3; c++)
        {
            new_image.at<cv::Vec3b>(y,x)[c] = 
            cv::saturate_cast<uchar>(alpha * (image.at<cv::Vec3b>(y,x)[c]) + beta);
        }
        }
    }
    cv::imshow("contrast", new_image);

    /* Convert RGB Mat into HSV color space */

    cv::Mat hsv;
    cv::cvtColor(new_image, hsv, CV_BGR2HSV);
    std::vector<cv::Mat> v;
    cv::split(hsv,v);

    // Perform threshold on the S channel of hSv    
    int thres = 15;
    cv::threshold(v[1], v[1], thres, 255, cv::THRESH_BINARY_INV);
    cv::imshow("saturation", v[1]);

    /* Erode & Dilate */

    int erosion_size = 6;   
    cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS,
                          cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1), 
                          cv::Point(erosion_size, erosion_size) );
    cv::erode(v[1], v[1], element);
    cv::dilate(v[1], v[1], element);    
    cv::imshow("binary", v[1]);

    /* Bounding box */

    // Invert colors
    cv::bitwise_not(v[1], v[1]);

    // Store the set of points in the image before assembling the bounding box
    std::vector<cv::Point> points;
    cv::Mat_<uchar>::iterator it = v[1].begin<uchar>();
    cv::Mat_<uchar>::iterator end = v[1].end<uchar>();
    for (; it != end; ++it)
    {
        if (*it) points.push_back(it.pos());
    }    

    // Compute minimal bounding box
    cv::RotatedRect box = cv::minAreaRect(cv::Mat(points));

    // Draw bounding box in the original image (debug purposes)
    cv::Point2f vertices[4];
    box.points(vertices);
    for (int i = 0; i < 4; ++i)
    {
        cv::line(image, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 2, CV_AA);
    }

    cv::imshow("box", image);    
    cvWaitKey(0);

    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否有可能在 emgucv 中找到“斑点”区域的边缘? 的相关文章

  • 如何获取列表框中项目的索引?

    我正在将项目添加到ListBox像这样 myListBox Items addRange myObjectArray 我还想通过以下方式选择我添加的一些项目 foreach MyObject m in otherListOfMyObject
  • 将 python 字典翻译为 C++

    我有包含以下代码的 python 代码 d d 0 0 0 d 1 2 1 d 2 1 2 d 2 3 3 d 3 2 4 for i j in d print d i j d j i 不幸的是 对于我的目的来说 循环遍历 python 中
  • 从列表中获取数组而不进行堆分配

    我有一个列表 我想将其数组分配给一个属性 public void BuildMesh List
  • 在 C# 中将 Exe 文件作为嵌入式资源运行

    我有一个第 3 方 EXE 我只需要从我的 C 应用程序运行它 我的主要目标是对我的 C 文件中的第 3 方可执行文件进行版权保护 有没有更好的方法来做到这一点 我怎样才能做到这一点 首先将嵌入的可执行文件作为资源文件添加到您现有的资源文件
  • 图像的 EMGU/OpenCV FFT 未产生预期结果

    我正在尝试使用 EMGU 可视化图像的 FFT 这是我正在处理的图像 这是预期的结果 Here s what I get 这是我的代码 Image
  • Tulpep PopupNotifier 无法与计时器一起使用

    using System using System Data SQLite using System Drawing using System Timers using System Windows Forms using Tulpep N
  • std::function 中参数的自动动态转换

    我们有多态类 A 和 B 例如 struct A virtual A struct B final public A void f std cout lt lt f lt lt std endl 我想分配一个变量std function
  • 使用signinmanager成功登录后,用户仍然显示为已注销?

    我已将 Asp Net 身份框架添加到从前端调用的 WebAPI 中 注册帐户后 并看到它在数据库中正确显示 我使用该用户的用户名和密码登录 结果成功 但根据登录管理器 用户未登录 我尝试使用 cookie 身份验证使用此示例 https
  • UWP 关闭信息亭模式

    我有一个发布到 Windows 应用商店的 UWP 应用程序 并且该应用程序可以启动进入信息亭模式 分配访问权限 它工作得很好 但我尝试在应用程序上创建一个按钮来关闭信息亭模式并返回到 Windows 登录屏幕 我尝试了文档中给出的代码 h
  • 按下按钮时更改几何绘图画笔的颜色

    我创建了一个按钮模板 有一个图像和一个标签 图像的来源位于 ResourceDictionary Pictures 中 图片的来源是具有白色画笔颜色的 DrawingImage
  • OpenMP while 循环中的手动同步

    我最近开始使用 OpenMP 为大学的一个项目做一些 研究 我有一个矩形且均匀分布的网格 在该网格上我使用迭代方案求解偏微分方程 因此 我基本上有两个 for 循环 网格的 x 方向和 y 方向各一个 并由 while 循环包裹以进行迭代
  • 为什么转发引用与右值引用具有相同的语法?

    我刚刚对这些 相当 新的功能做了一些研究 我想知道为什么 C 委员会决定为它们引入相同的语法 看来开发人员不必要浪费一些时间来理解它是如何工作的 而一种解决方案可以让我们思考进一步的问题 就我而言 它是从问题开始的 可以简化为 includ
  • 在 C++ 中的 Switch-Case 中执行 OR 运算

    你会如何在 C 中做到这一点 例如 如果用户按 ESC 或 q 或 Q 我试图触发程序退出 我尝试寻找它 但在 C 中没有找到它的语法 我知道如何使用 if else 来做到这一点 但是可以使用 switch case 来做到这一点吗 当然
  • 非静态类中的静态方法有什么意义?

    我无法理解以下代码的潜在错误 class myClass public void print string mess Console WriteLine mess class myOtherClass public static void
  • 在memcpy缓冲区UB上使用reinterpret_cast吗?

    给定代码 struct A auto obj new A std vector
  • 使用 DI 将参数传递给 DbContext

    我想向 DBContext 传递一个附加参数 如下所示 string myParam xx string con connenctionstring services AddDbContext
  • C++中main函数可以调用自身吗?

    谁能告诉我下面的代码有什么问题吗 int main return main 我测试了一下 编译正确 它永远运行 幕后还有什么阴谋吗 TLDR 呼叫main导致未定义的行为 标准中使用的术语以及对程序员和编译器的影响似乎存在混淆 首先 单独的
  • 创建 MSI 的最佳工具[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我是设置项目创建的新手 现在我正在使用 Visual Studio 2008 为我的项目创建安装文件 msi 我对在安装向导中创建自己的自
  • 用 C# 解析和查询 SOAP

    我正在尝试解析一个大量命名空间的 SOAP 消息 源也可以在here http tinyurl com n3av6k
  • 如何在 Ubuntu x64 中使用 ptrace 插入 int3?

    我正在努力追随本指南 http eli thegreenplace net 2011 01 27 how debuggers work part 2 breakpoints 通过设置断点达到相同的结果 唯一的区别是我在 x64 系统上 所以

随机推荐