将图像读取为线条的算法(然后得到它们的结果)?

时间:2016-08-29 21:55:17

标签: javascript algorithm image-processing

是否有算法从像素中获取图像的线条划线(忽略曲线,圆圈等,一切都将被视为线条,但仍然类似于矢量)?然后得到它们的结果,如Array

这就是它基本上如何阅读

Basic read

这样,每行像素将被读作1条水平线,我也想处理垂直线;但是如果有一个圆形的脂肪线需要超过1行

round fat line

它将被视为一行。它的线宽与像素的高度相同。

例如,假设我们有一个包含(红色,绿色,蓝色,alpha)格式(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
    ])
]

这将是一个2x2px的图像数据,具有直的水平红线。所以,从这个数组中,我想得到一个包含行数据的数组,如:

[
    // 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] }
]

注意:我想处理抗锯齿。

这是我以上述格式读取像素的功能:

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

2 个答案:

答案 0 :(得分:3)

您可以使用Hough transform找到所有行。它只能找到线条,没有曲线或圆圈。您可能需要在查找行之前运行边缘检测。这是一个例子: enter image description here enter image description here

Here你可以找到opencv实现的例子。

答案 1 :(得分:3)

我有一次类似的图像处理问题,你可以阅读它here。但是你可以基本上对想要对图像做的任何事情采取相同的想法。

基本数据如下:

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. 
}

<强>更新

查找颜色数据的工作示例;

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

可以看到更多示例here

上面的作者概述了像素和行数据:

变量data引用的ImageData.data属性是一维整数数组,其中每个元素的范围为0..255。 ImageData.data按重复顺序排列,以便每个元素引用单个通道。重复序列如下:

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