Pixel chains from path length coding

I fought for a long time on this head

I am making images. So far, I have converted my images to binary, which means that every pixel under a certain value is discarded from the image in grayscale. This gives me only some areas from the original image with a lot of “zero pixels” around these areas.

Then I ran the length, encoded my regions into "drops". Runs are a data compression method. For example, suppose you digitize a square, you will have only a few runs describing the entire image. Trails are defined by x, y coordinates and length.

When you recreate the image for each run, go to the x, y coordinates and add pixels on the x axis for the length of the run.

Now I need to take the route and create a chain from it that will describe the outline of the region. I do not know how to do that.

I have a bunch of x, y, trace lengths, and I need to "move" around the edges to form a chain . Usually, when processing images, this process is performed with the original image, but I can no longer use the original image here, so I have to calculate it from the runs.

I know this sounds like a big wall of text, but I don't know how best to ask this question.

Any hints or pointers to an identical implementation would be great.

EDIT

thanks untwist, I will make a link to several images:

alt text
(source: tudelft.nl )

B C ( ). D,

+3
3

, , Freeman Chain

, , , , .

0

. . , :

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

(, A = 0, B = 127,...). ( ). :

ABBBAAAAAAAAAACDDDDDDDD
CDDDDAAACCCCCCAAAAAAAAA

, . , , , , .

0

(++):

#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;
        }
    }

}

, , , : , , . , , , .

, , !

0

Source: https://habr.com/ru/post/1732484/


All Articles