javascript - Algorithm for reading image as lines (then get a result of them)? - Stack Overflow

Is there a algorithm to get the line strokes of a image (ignore curves, circles, etc., everything will

Is there a algorithm to get the line strokes of a image (ignore curves, circles, etc., everything will be treated as lines, but still similiar to vectors), from their pixels? Then get a result of them, like a Array?

This is how it'd basically work to read

In this way, each row of pixel would be read as 1 horizontal line and I'd like to handle vertical lines also; but if there's a round fat line that takes more than 1 row

it'll be considered one line. Its line width is the same height of pixels it has.

For instance, let's suppose we've a array containing rows of pixels in the (red, green, blue, alpha) format (JavaScript):

/* formatted ImageData().data */
[
    new Uint8Array([
        /* first pixel */
        255, 0, 0, 255,
        /* second pixel */
        255, 0, 0, 255
    ]),

    new Uint8Array([
        /* first pixel */
        0, 0, 0, 0,
        /* second pixel */
        0, 0, 0, 0
    ])
]

This would be a 2x2px image data, with a straight horizontal red line. So, from this array, I want to get a array containing data of lines, like:

[
    // x, y: start point
    // tx, ty: end point
    // w: line width

    // the straight horizontal red line of 1 pixel
    { x: 0, y: 0, tx: 2, ty: 0, w: 1, rgba: [255, 0, 0, 255] }
]

Note: I'd like to handle anti-aliasing.

This is my function to read pixels in the above format:

var getImagePixels = function(img){
    var canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d');

    canvas.width = img.width;
    canvas.height = img.height;

    ctx.drawImage(img, 0, 0);

    var imgData = ctx.getImageData(0, 0, img.width, img.height).data;
    var nImgData = [];
    var offWidth = img.width * 4;

    var dataRow = (nImgData[0] = new Uint8Array(offWidth));

    for (var b = 0, i = 0; b++ < img.height;) {
        nImgData[b] = new Uint8Array(offWidth);

        for (var arrI = 0, len = i + offWidth; i < len; i += 4, arrI += 4) {
            nImgData[b][arrI] = imgData[i];
            nImgData[b][arrI + 1] = imgData[i + 1];
            nImgData[b][arrI + 2] = imgData[i + 2];
            nImgData[b][arrI + 3] = imgData[i + 3];
        }
    }

    return nImgData;
};

Is there a algorithm to get the line strokes of a image (ignore curves, circles, etc., everything will be treated as lines, but still similiar to vectors), from their pixels? Then get a result of them, like a Array?

This is how it'd basically work to read

In this way, each row of pixel would be read as 1 horizontal line and I'd like to handle vertical lines also; but if there's a round fat line that takes more than 1 row

it'll be considered one line. Its line width is the same height of pixels it has.

For instance, let's suppose we've a array containing rows of pixels in the (red, green, blue, alpha) format (JavaScript):

/* formatted ImageData().data */
[
    new Uint8Array([
        /* first pixel */
        255, 0, 0, 255,
        /* second pixel */
        255, 0, 0, 255
    ]),

    new Uint8Array([
        /* first pixel */
        0, 0, 0, 0,
        /* second pixel */
        0, 0, 0, 0
    ])
]

This would be a 2x2px image data, with a straight horizontal red line. So, from this array, I want to get a array containing data of lines, like:

[
    // x, y: start point
    // tx, ty: end point
    // w: line width

    // the straight horizontal red line of 1 pixel
    { x: 0, y: 0, tx: 2, ty: 0, w: 1, rgba: [255, 0, 0, 255] }
]

Note: I'd like to handle anti-aliasing.

This is my function to read pixels in the above format:

var getImagePixels = function(img){
    var canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d');

    canvas.width = img.width;
    canvas.height = img.height;

    ctx.drawImage(img, 0, 0);

    var imgData = ctx.getImageData(0, 0, img.width, img.height).data;
    var nImgData = [];
    var offWidth = img.width * 4;

    var dataRow = (nImgData[0] = new Uint8Array(offWidth));

    for (var b = 0, i = 0; b++ < img.height;) {
        nImgData[b] = new Uint8Array(offWidth);

        for (var arrI = 0, len = i + offWidth; i < len; i += 4, arrI += 4) {
            nImgData[b][arrI] = imgData[i];
            nImgData[b][arrI + 1] = imgData[i + 1];
            nImgData[b][arrI + 2] = imgData[i + 2];
            nImgData[b][arrI + 3] = imgData[i + 3];
        }
    }

    return nImgData;
};
Share Improve this question edited Sep 5, 2016 at 12:17 asked Aug 29, 2016 at 21:55 user5066707user5066707 22
  • 2 I think what you may want is an edge filter. – jedifans Commented Aug 29, 2016 at 21:57
  • 1 That one I'm not sure about, sorry. Hopefully someone else can help :) – jedifans Commented Aug 29, 2016 at 21:59
  • 2 GIMP has a lot of filters open sourced, have a look at them – Déjà vu Commented Sep 1, 2016 at 0:12
  • 1 Here's a start point: youtube./… – Ismael Miguel Commented Sep 1, 2016 at 0:21
  • 1 Can you restrict the problem at all? Must it handle transparency? Different colored lines? What kinds of curves - none? Semicircle? Quadratic? More plex? What about an arbitrary pen squiggle, should it handle that? Must it handle antialiasing? And, do you really need to do this to so many images that it isn't faster to just trace things with the pen tool in Photoshop? – twhb Commented Sep 1, 2016 at 0:42
 |  Show 17 more ments

2 Answers 2

Reset to default 2 +25

You can find all lines using Hough transform. It will find only lines, no curves or circles. You may need to run edge detection before finding lines. Here is example:

Here you can find opencv example of implementation.

I had a similar image processing question once, you can read it here. But you can basically take the same idea for anything you want to do with an image.

The basic data can be seen as follows:

var img = new Image,
    w = canvas.width,
    h = canvas.height,
    ctx = canvas.getContext('2d');

img.onload = imgprocess;
img.src = 'some.png';

function imgprocess() { 
    ctx.drawImage(this, 0, 0, w, h);

    var idata = ctx.getImageData(0, 0, w, h),
    buffer = idata.data,
    buffer32 = new Uint32Array(buffer.buffer),
    x, y,
    x1 = w, y1 = h, x2 = 0, y2 = 0;

    //You now have properties of the image from the canvas data. You will need to write your own loops to detect which pixels etc... See the example in the link for some ideas. 
}

UPDATE:

Working example of finding color data;

var canvas = document.getElementById('canvas');
var canvasWidth  = canvas.width;
var canvasHeight = canvas.height;
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);

var buf = new ArrayBuffer(imageData.data.length);
var buf8 = new Uint8ClampedArray(buf);
var data = new Uint32Array(buf);

for (var y = 0; y < canvasHeight; ++y) {
    for (var x = 0; x < canvasWidth; ++x) {
        var value = x * y & 0xff;

        data[y * canvasWidth + x] =
            (255   << 24) |    // alpha
            (value << 16) |    // blue
            (value <<  8) |    // green
             value;            // red
    }
}

More examples can be seen here

The author above outlines pixel and line data:

The ImageData.data property referenced by the variable data is a one-dimensional array of integers, where each element is in the range 0..255. ImageData.data is arranged in a repeating sequence so that each element refers to an individual channel. That repeating sequence is as follows:

data[0]  = red channel of first pixel on first row
data[1]  = green channel of first pixel on first row
data[2]  = blue channel of first pixel on first row
data[3]  = alpha channel of first pixel on first row

data[4]  = red channel of second pixel on first row
data[5]  = green channel of second pixel on first row
data[6]  = blue channel of second pixel on first row
data[7]  = alpha channel of second pixel on first row

data[8]  = red channel of third pixel on first row
data[9]  = green channel of third pixel on first row
data[10] = blue channel of third pixel on first row
data[11] = alpha channel of third pixel on first row

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744865997a4597980.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信