曲线/路径骨架二值图像处理

2024-05-10

我正在尝试开发一个可以处理图像骨架的路径/曲线的代码。我想要一个来自两点之间骨架的点向量。

该代码在添加一些点后结束。我没有找到解决方案。

 #include "opencv2/highgui/highgui.hpp"
 #include "opencv2/imgproc/imgproc.hpp"
 #include "opencv2/imgproc/imgproc_c.h"
 #include <opencv2/legacy/compat.hpp>
 #include <opencv2/core/core.hpp>
 #include <iostream>
 #include <cmath>
 #include <list>
 using namespace cv;
 using namespace std;

  //this method to find the 8-neighbors of a point from image 
 vector<Point> search8Neighbor(cv::Mat mat,Point startPoint)
 {
  vector<Point> segment;
  Point p;
    //uchar p1 = mat.at<uchar>(startPoint.x, startPoint.y);
    uchar p2 = mat.at<uchar>(startPoint.x-1, startPoint.y);
    uchar p3 = mat.at<uchar>(startPoint.x-1, startPoint.y+1);
    uchar p4 = mat.at<uchar>(startPoint.x, startPoint.y+1);
    uchar p5 = mat.at<uchar>(startPoint.x+1, startPoint.y+1);
    uchar p6 = mat.at<uchar>(startPoint.x+1, startPoint.y);
    uchar p7 = mat.at<uchar>(startPoint.x+1, startPoint.y-1);
    uchar p8 = mat.at<uchar>(startPoint.x, startPoint.y-1);
    uchar p9 = mat.at<uchar>(startPoint.x-1, startPoint.y-1);

    //if(p1==255) segment.push_back(startPoint.x, startPoint.y);
    if (p2 == 255) {
            p.x=startPoint.x-1;
            p.y=startPoint.y;
            segment.push_back(p);
    }
    if(p3==255) {
            p.x=startPoint.x-1;
            p.y=startPoint.y+1;
            segment.push_back(p);
    }

    if(p4==255) {
            p.x=startPoint.x;
            p.y=startPoint.y+1;
            segment.push_back(p);
    }

    if(p5==255) {
            p.x=startPoint.x+1;
            p.y=startPoint.y+1;
            segment.push_back(p);
    }

    if(p6==255) {
            p.x=startPoint.x+1;
            p.y=startPoint.y;
            segment.push_back(p);
    }
    if(p7==255) {
            p.x=startPoint.x+1;
            p.y=startPoint.y-1;
            segment.push_back(p);
    }
    if(p8==255){
            p.x=startPoint.x;
            p.y=startPoint.y-1;
            segment.push_back(p);
    }

    if(p9==255) {
            p.x=startPoint.x-1;
            p.y=startPoint.y-1;
            segment.push_back(p);
    }

    return segment ;

 }
  //this method return a vector of points from a skeleton that contains all the points 
 //  between a start point "peak" and an end point 
 //this method use the idea of Breadth first search 
  vector<Point> traceLine(Mat img , Point peak)
{
    vector<Point> vect1;
    vector<Point> vect2;
    img.at<uchar>(peak.x,peak.y)=0;//
    vect1.push_back(peak);//add peak to vect1
    while(vect1.size() != 0)
        {
        Point p=vect1[0];
        vect1.erase(vect1.begin());
        vect2.push_back(p);
        vector<Point> vectN;
        vectN=search8Neighbor(img,p);
        vector<Point>::iterator it;
        it = vect1.begin();
        //cout<<vectN.size()<<endl;
        for(int i=0;i<vectN.size();i++)
            {
                 img.at<uchar>(vectN[i].x,vectN[i].y)=0;
                vect1.insert(it,vectN[i]);

            }
        }
return vect2;
}

int main( int argc, char** argv )
{
cv::Mat im = cv::imread("aa.jpg",0);
if (im.empty())
return -1;
 cv::Mat img;
cv::threshold(im, img, 155, 255, CV_THRESH_BINARY);
vector<Point> vect1;
Point p;
p.x=20;
p.y=30;
if(mat.at<uchar>(p.x-1, p.y)==255)
vect1=traceLine(img,p);
imshow("image",im);
cv::waitKey();
return 0 ;
}

Mat 以矩阵的正常行/列方式索引,所以你想要mat.at<uchar>(y, x), not mat.at<uchar>(x, y),否则会导致混乱。

您所在的地方:

vector<Point>::iterator it;
it = vect1.begin();
...
for(...)
    vect1.insert(it,vectN[i]);

如果插入导致缓冲区被重新分配,这将会中断,因为它随后指向一些已被释放的内存,或者可能被重新分配给其他东西。 而是使用

 vect1.insert(vect1.begin(),vectN[i]);

(这将给出与您的程序似乎执行的操作略有不同的顺序)或使用push_back()真正获得广度优先的行为。

最大的问题是在 search8Neighbor() 中。你在哪里有uchar p2 = mat.at<uchar>(startPoint.x-1, startPoint.y);如果 startPoint 引用图像边缘的像素会发生什么?您将引用图像外部的像素,并且程序将偏离,直到发生异常。在这里,您需要检查您在图像中的位置,并确保邻域中不包含图像外部的像素。

EDIT我不相信如果按照我所说的进行更改,代码将无法工作。 我已经实施了修复并且它有效:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include <opencv2/legacy/compat.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
#include <cmath>
#include <list>
using namespace cv;
using namespace std;

 // Find the 8-neighbors of a point from image.
 vector<Point> search8Neighbor(cv::Mat mat,Point startPoint)
 {
    vector<Point> neighbors;
    vector<Point> offsets;
    offsets.push_back(Point(-1,  0)); // p2
    offsets.push_back(Point(-1,  1)); // p3
    offsets.push_back(Point( 0,  1)); // p4
    offsets.push_back(Point( 1,  1)); // p5
    offsets.push_back(Point( 1,  0)); // p6
    offsets.push_back(Point( 1, -1)); // p7
    offsets.push_back(Point( 0, -1)); // p8
    offsets.push_back(Point(-1, -1)); // p9

    vector<Point>::iterator it;
    for(it = offsets.begin(); it < offsets.end(); ++it)
    {
        if(!((it->x < 0 && startPoint.x == 0)
            || (it->y < 0 && startPoint.y == 0)
            || (it->x > 0 && startPoint.x == mat.cols - 1)
            || (it->y > 0 && startPoint.y == mat.rows - 1)))
        {
            Point p(startPoint + *it);
            if(mat.at<uchar>(p) == 255)
                neighbors.push_back(p);
        }
    }

    return neighbors;
 }

 //this method return a vector of points from a skeleton that contains all the points 
 //  between a start point "peak" and an end point 
 //this method use the idea of Breadth first search 
  vector<Point> traceLine(Mat img , Point peak)
{
    vector<Point> vect1;
    vector<Point> vect2;
    img.at<uchar>(peak.y, peak.x)=0;//
    vect1.push_back(peak);//add peak to vect1
    while(vect1.size() != 0)
        {
        Point p=vect1[0];
        vect1.erase(vect1.begin());
        vect2.push_back(p);
        vector<Point> vectN;
        vectN = search8Neighbor(img, p);

        //cout<< " vectN.size()=" << vectN.size()<<endl;

        for(int i = 0; i < int(vectN.size()); ++i)
            {
                img.at<uchar>(vectN[i].y, vectN[i].x)=0;
                vect1.push_back(vectN[i]);
            }
        }
    return vect2;
}

int main( int argc, char** argv )
{
    cv::Mat im = cv::imread("aa.jpg",0);
    if (im.empty())
        return -1;
    cv::Mat img;
    cv::threshold(im, img, 155, 255, CV_THRESH_BINARY);
    imshow("thresholded image",im);
    vector<Point> vect1;

    Point p(3, 32);
    uchar u = img.at<uchar>(p.x, p.y);
    if(img.at<uchar>(p) == 255)
        vect1 = traceLine(img, p);

    Mat output(im.rows, im.cols, CV_8UC3, Scalar(0, 0, 0));
    vector<Point>::iterator it;

    for(it = vect1.begin(); it < vect1.end(); ++it)
    {
        Vec3b green(0, 255, 0);
        output.at<Vec3b>(*it) = green;
    }
    imshow("output", output);
    cv::waitKey();
    return 0 ;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

曲线/路径骨架二值图像处理 的相关文章

随机推荐

  • React Native 运行保持在 IDLE 状态

    这是我第一次设置 React NativeUbuntu 18 04 LTS 我已经完成设置 并且尝试使用以下命令在设备上运行该应用程序react native run android命令 这是我在终端中得到的输出 ron lenovo re
  • OpenSSL:无需 SSL_read() / SSL_write() 即可执行加密/解密

    我已经用 C 语言编写了一个基于事件的网络库 现在我想通过 OpenSSL 添加 SSL TLS 支持 而不是使用SSL read and SSL write 我宁愿让 OpenSSL 只执行传出 传入数据的加密 解密 让我自己传输 接收数
  • 有没有用 Javascript 编写的开源 JSDoc 解析器?

    我正在寻找一个可以在我的项目中使用的 JSDoc 解析器 我正在寻找可以传递 JSDoc 注释并接收该注释含义的结构化描述的东西 我见过的大多数工具似乎都能够将 JSDoc 注释转换为 HTML 或其他格式 我正在寻找能够提供可用于输入其他
  • 使用 NSCoder 编码 CGPoint 结构

    如何编码和解码CGPoint结构使用NSCoder 编码 CGPoint point point from somewhere NSValue pointValue NSValue value point withObjCType enco
  • 为什么在 C++ 类中的数据成员上使用像 m_ 这样的前缀?

    许多 C 代码使用语法约定来标记数据成员 常见的例子包括 m memberName对于公共成员 在所有使用公共成员的情况下 memberName对于私人会员或所有会员 其他人尝试强制使用this gt member每当使用数据成员时 根据我
  • 如何在不打开邮件的情况下加载 Gmail 插件

    我们需要开发 gmail 插件来读取已检查的邮件消息并处理内容 我们使用以下应用程序 json oauthScopes https www googleapis com auth gmail addons execute https www
  • 提升shared_from_this<>()

    有人可以用几句话概括一下如何提升shared from this lt gt 应该使用智能指针 特别是从使用绑定函数在 io service 中注册处理程序的角度来看 编辑 一些回复要求提供更多背景信息 基本上 我正在寻找 陷阱 即人们使用
  • 智能感知不显示评论

    如果我在 Visual Studio 2010 中输入类似的内容数据集1 我得到所有可用方法和属性的列表 智能感知 这很好用 但是 如果我在此列表中选择一个方法或属性 我不会得到 if 的描述 例如 如果我有类似的东西 public cla
  • 为什么spring boot 1.5.3 jar无法识别src/main/resources/META-INF/resources/中的jsp文件

    我使用了spring boot jsp 我想构建一个可执行的jar 如下这个帖子 http www logicbig com tutorials spring framework spring boot boot serve dynamic
  • 在 C++ 中什么时候首选传递指针而不是引用传递?

    我可以想象一种情况 其中输入参数可以为 NULL 以便首选传递指针而不是传递引用 有人可以添加更多案例吗 在传递的对象实际上将被修改的情况下 有些人更喜欢传递指针 当对象通过引用传递时 它们使用 pass by const referenc
  • 会话过期后如何重定向到登录页面?

    我有三个 JSF 2 0 Web 模块 当会话过期时我需要重定向到登录页面 我已经尝试过使用HttpSessionListener 它正在调用sessionDestroyed 事件方法 但我无法在那里转发 重定向请求 我认为这是因为没有Ht
  • 你能测试一下 mixin 是否存在吗?

    Sass 快速提问 希望如此 你能测试 mixin 是否存在吗 例如 if thumbnail mixin else define mixin 理想情况下我会使用 unless 但这只存在于叉子上 我知道你可以覆盖 mixin 但我想更多的
  • iOS 中的视频可以进行反卷积吗?

    我想拍摄击球手挥动棒球的镜头 但球棒很模糊 视频为 30 fps 通过研究 我发现反卷积似乎是最小化运动模糊的方法 但我不知道是否或如何在我的 iOS 应用程序后处理中实现它 我希望有人能给我指出正确的方向 比如如何在 iOS 中应用反卷积
  • QGraphicsView 和 eventFilter

    这个问题已经困扰我两天多了 所以我想我应该问一下 我在Win7上使用Qt 4 5 3 用VC2008编译 我有 MyGraphicsView 继承 QGraphicsView 和 MyFilter 继承 QObject 类 当我将 MyFi
  • 当 QML 对象不可见时防止 QML 属性绑定?

    我正在开发一个具有大量属性绑定的 QML 应用程序 数百个对象被跟踪并以不同的形式显示 例如 Qt3D QCanvas 当我在应用程序的单独页面上时 x y 位置和相对大小的属性绑定仍在发生 我怎样才能阻止他们 我知道我可以根据属性是否可视
  • 无法构建项目输出组内容文件

    目前 我正在尝试使用 Visual Studio 2010 为我们的 ASP net4 Silverlight Web 应用程序之一创建一个 WebSetup 项目 我根据创建了安装项目this http weblogs asp net s
  • 为什么 getch 不可移植?

    是什么使得 getch 本质上无法作为标准 C 函数包含在内 对于控制台界面来说 它是如此直观和优雅 如果没有它 要求输入单个字符总是会产生误导 因为用户可以输入多个键 更糟糕的是 您经常需要确保在读取控制台输入后清除标准输入 这甚至不是作
  • 集成 Windows 身份验证可以在 Firefox 中使用吗?

    如果我的 ASP NET 应用程序是使用 Windows 集成身份验证为 ADFS 设置的 我知道这可以在 IE 中工作 但是它可以在 Firefox 中工作吗 我在网络上看到一些内容表明存在问题 您需要在每个客户端浏览器中设置解决方法 h
  • 在 Haskell 中增长数组

    我想在 Haskell 中实现以下 命令式 算法 给定一个序列对 e0 s0 e1 s1 e2 s2 en sn 其中 e 和 s 部分不一定是自然数不同的是 在每个时间步都会随机选择该序列的一个元素 例如 ei si 并根据 ei si
  • 曲线/路径骨架二值图像处理

    我正在尝试开发一个可以处理图像骨架的路径 曲线的代码 我想要一个来自两点之间骨架的点向量 该代码在添加一些点后结束 我没有找到解决方案 include opencv2 highgui highgui hpp include opencv2