来自游程编码的像素链

发布于 2024-08-21 10:33:44 字数 940 浏览 6 评论 0原文

绞尽脑汁很长时间了

我已经为我正在进行的成像工作 。到目前为止,我已经对图像进行了二值化,这意味着从灰度图像中,低于特定值的每个像素都会被丢弃。这给了我原始图像中的一些区域,这些区域周围有很多“零像素”。

接下来,我将我的区域运行长度编码为“斑点”。运行是一种数据压缩方法。例如,假设您对一个正方形进行了二值化,那么您将只有几次运行来描述整个图像。 行程由 x,y 坐标和长度定义。

重新创建图像时,对于每次运行,转到 x,y 坐标并在 x 轴上添加运行长度的像素。

现在我必须进行运行并从中创建一条链来描述该区域的轮廓。 我不知道该怎么做。

我有一堆 x,y,length 运行,我必须在边缘“导航”以形成 。通常在成像中,这个过程是使用原始图像完成的,但我在这里不能再使用原始图像,所以我必须通过运行来计算它。

我知道这看起来像是一堵大文字墙,但我不知道如何更好地提出这个问题。

关于相同实现的任何提示或指示都会很棒。

编辑

感谢放松,我将链接一些图像:

alt 文本
(来源:tudelft.nl

在这个例子中,他们将图像 B 处理成轮廓 C(我称之为链)。不过我想从 D(游程长度)生成轮廓

I've been banging my head for a long time on this one

I am doing imaging. So far I've binarized my images, meaning that from a grayscale image, every pixel under a certain value are dropped. This gives me only some regions out of the original image with a lot of "zero pixels" all around those regions.

Next I've run length encoded my regions into "blobs". Runs are a method of compression for data. For example, suppose that you have binarized a square, the you will have only a few runs describing the whole image.
The runs are defined by x,y coordinates and a length.

When recreating the image, for each run, go to x,y coordinate and add pixels on the x axis for the length of the run.

Now I have to take the runs and create a chain out of it that will describe the contour of the region.
I don't know how to do that.

I have a bunch of x,y,length runs and I have to "navigate" around the edges to form a chain. Normally in imaging this process is done with the original image but I can't use the original image anymore here so I have to compute it with the runs.

I know this looks like a big wall of text but I don't know how to ask this question better.

Any hints or pointers on identical implementation would be awesome.

EDIT

thanks to unwind, Ill link a few images :

alt text
(source: tudelft.nl)

In this example, they process the image B into the contour C (which I call chain). However I'd like to generate the contour from D, the Run Lengths

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

回忆追雨的时光 2024-08-28 10:33:44

乍一看,我没有看到一个实用的算法。
穷人的解决方案是从长度编码的图像中扩展原始图像。
因此,如果您的行如下所示:

A 3B 10A C 8D
C 4D 3A 6C 9A

其中字符返回实际像素值(例如 A = 0,B = 127,...)。
您可以将像素值写入二维数组(或您选择的其他数据结构)。它看起来像这样:

ABBBAAAAAAAAAACDDDDDDDD
CDDDDAAACCCCCCAAAAAAAAA

然后生成链,删除数组并保留链信息。
当然,这很昂贵,所以也许您可以在对原始图片进行长度编码之前执行此操作。

At first glance I don't see a practical algorithm for that.
A poor man's solution would be expand the original image from the length encoded one.
So if your lines look like this:

A 3B 10A C 8D
C 4D 3A 6C 9A

where the characters return the actual pixel value ( e.g. A = 0, B = 127,...).
You could write the pixel values into a two dimensional array (or another datastructure of your choice).It looks like this:

ABBBAAAAAAAAAACDDDDDDDD
CDDDDAAACCCCCCAAAAAAAAA

Afterwards generate your chain, delete the array and keep the chain information.
Sure this is expensive so maybe you could do this before length-encoding the original picture.

め七分饶幸 2024-08-28 10:33:44

这是一个非常简单且实用的解决方案(C++):

#include <iostream>
#include <vector>

struct Run { int x, w; };
enum { EAST, NORTHEAST, NORTH, NORTHWEST, WEST, SOUTHWEST, SOUTH, SOUTHEAST };

int main() {

    const Run data[] = {
        { 7, 2 },
        { 5, 6 },
        { 5, 7 },
        { 5, 7 },
        { 6, 6 },
        { 0, 12 },
        { 0, 12 },
        { 0, 11 },
        { 1, 7 },
        { 3, 4 },
        { 3, 4 },
        { 3, 5 },
        { 3, 7 },
        { 3, 7 },
        { 5, 5 }
    };

    std::vector<Run> runs(data, data + 15);
    std::vector<int> before;
    std::vector<int> after;
    unsigned int i;
    int j;

    for (i = 0; i < runs.size() - 1; ++i) {

        if (runs[i].x < runs[i + 1].x) {

            for (j = 0; j < runs[i + 1].x - runs[i].x - 1; ++j)
                before.push_back(WEST);
            before.push_back(NORTHWEST);

        } else if (runs[i].x > runs[i + 1].x) {

            before.push_back(NORTHEAST);
            for (j = 0; j < runs[i].x - runs[i + 1].x - 1; ++j)
                before.push_back(EAST);

        } else {

            before.push_back(NORTH);

        }

        int first_right(runs[i].x + runs[i].w);
        int second_right(runs[i + 1].x + runs[i + 1].w);

        if (first_right < second_right) {

            after.push_back(SOUTHEAST);
            for (j = 0; j < second_right - first_right - 1; ++j)
                after.push_back(EAST);

        } else if (first_right > second_right) {

            for (j = 0; j < first_right - second_right - 1; ++j)
                after.push_back(WEST);
            after.push_back(SOUTHWEST);

        } else {

            after.push_back(SOUTH);

        }

    }

    for (j = 0; j < runs.back().w - 1; ++j)
        after.push_back(WEST);

    std::reverse(before.begin(), before.end());
    after.insert(after.end(), before.begin(), before.end());

    for (j = 0; j < int(after.size()); ++j) {
        switch (after[j]) {
        case EAST:      std::cout << "EAST\n";      break;
        case NORTHEAST: std::cout << "NORTHEAST\n"; break;
        case NORTH:     std::cout << "NORTH\n";     break;
        case NORTHWEST: std::cout << "NORTHWEST\n"; break;
        case WEST:      std::cout << "WEST\n";      break;
        case SOUTHWEST: std::cout << "SOUTHWEST\n"; break;
        case SOUTH:     std::cout << "SOUTH\n";     break;
        case SOUTHEAST: std::cout << "SOUTHEAST\n"; break;
        }
    }

}

它的工作原理是迭代运行,测试左右端点的跳跃方向,并将适当数量的链元素添加到两个向量:一个按正向顺序,用于右侧,以及相反的顺序,用于左侧。然后,它通过为最后一条扫描线添加适当数量的链接来连接两条链,然后反转左侧链并将其附加到右侧链以生成最终链。

希望这就是您正在寻找的!

Here's a perfectly simple and practical solution (C++):

#include <iostream>
#include <vector>

struct Run { int x, w; };
enum { EAST, NORTHEAST, NORTH, NORTHWEST, WEST, SOUTHWEST, SOUTH, SOUTHEAST };

int main() {

    const Run data[] = {
        { 7, 2 },
        { 5, 6 },
        { 5, 7 },
        { 5, 7 },
        { 6, 6 },
        { 0, 12 },
        { 0, 12 },
        { 0, 11 },
        { 1, 7 },
        { 3, 4 },
        { 3, 4 },
        { 3, 5 },
        { 3, 7 },
        { 3, 7 },
        { 5, 5 }
    };

    std::vector<Run> runs(data, data + 15);
    std::vector<int> before;
    std::vector<int> after;
    unsigned int i;
    int j;

    for (i = 0; i < runs.size() - 1; ++i) {

        if (runs[i].x < runs[i + 1].x) {

            for (j = 0; j < runs[i + 1].x - runs[i].x - 1; ++j)
                before.push_back(WEST);
            before.push_back(NORTHWEST);

        } else if (runs[i].x > runs[i + 1].x) {

            before.push_back(NORTHEAST);
            for (j = 0; j < runs[i].x - runs[i + 1].x - 1; ++j)
                before.push_back(EAST);

        } else {

            before.push_back(NORTH);

        }

        int first_right(runs[i].x + runs[i].w);
        int second_right(runs[i + 1].x + runs[i + 1].w);

        if (first_right < second_right) {

            after.push_back(SOUTHEAST);
            for (j = 0; j < second_right - first_right - 1; ++j)
                after.push_back(EAST);

        } else if (first_right > second_right) {

            for (j = 0; j < first_right - second_right - 1; ++j)
                after.push_back(WEST);
            after.push_back(SOUTHWEST);

        } else {

            after.push_back(SOUTH);

        }

    }

    for (j = 0; j < runs.back().w - 1; ++j)
        after.push_back(WEST);

    std::reverse(before.begin(), before.end());
    after.insert(after.end(), before.begin(), before.end());

    for (j = 0; j < int(after.size()); ++j) {
        switch (after[j]) {
        case EAST:      std::cout << "EAST\n";      break;
        case NORTHEAST: std::cout << "NORTHEAST\n"; break;
        case NORTH:     std::cout << "NORTH\n";     break;
        case NORTHWEST: std::cout << "NORTHWEST\n"; break;
        case WEST:      std::cout << "WEST\n";      break;
        case SOUTHWEST: std::cout << "SOUTHWEST\n"; break;
        case SOUTH:     std::cout << "SOUTH\n";     break;
        case SOUTHEAST: std::cout << "SOUTHEAST\n"; break;
        }
    }

}

This works by iterating over the runs, testing the left and right endpoints for the direction they're jumping to, and adding the appropriate number of chain elements to two vectors: one in forward order, for the right side, and one in reverse order, for the left. It then connects the two chains by adding the appropriate number of links for the last scanline, then reverses the left side chain and appends it to the right one to produce the final chain.

Hope this is what you're looking for!

终难遇 2024-08-28 10:33:44

好吧,我失去了合同,但答案是使用 弗里曼链编码技术

事实上,它是游程编码,与算法无关,这与我之前的想法不同。

Well I lost that contract but the answer was to use the Freeman Chain Coding technique

The fact that it is run lengths encoding has nothing to do with the algorithm, unlike I previously thought.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文