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

Javascript 将图像读取为行的算法(然后得到它们的结果)?,javascript,algorithm,image-processing,Javascript,Algorithm,Image Processing,是否有一种算法可以从图像的像素中获取图像的线条笔划(忽略曲线、圆等,所有东西都将被视为线条,但仍然类似于向量)?然后得到它们的结果,比如数组 这就是阅读的基本原理 这样,每一行像素将被读取为一条水平线,我还想处理垂直线;但如果有一个圆形脂肪线,需要超过一排 这将被视为一条线。它的线宽与像素的高度相同 例如,假设我们有一个数组,其中包含(红、绿、蓝、阿尔法)格式(JavaScript)的像素行: 这将是一个2x2px的图像数据,带有一条笔直的水平红线。从这个数组中,我想得到一个包含行数据的数组

是否有一种算法可以从图像的像素中获取图像的线条笔划(忽略曲线、圆等,所有东西都将被视为线条,但仍然类似于向量)?然后得到它们的结果,比如
数组

这就是阅读的基本原理

这样,每一行像素将被读取为一条水平线,我还想处理垂直线;但如果有一个圆形脂肪线,需要超过一排

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

例如,假设我们有一个数组,其中包含(红、绿、蓝、阿尔法)格式(JavaScript)的像素行:

这将是一个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;
};
var getImagePixels=函数(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);
var nImgData=[];
var offWidth=img.width*4;
var dataRow=(nImgData[0]=新的Uint8Array(offWidth));
对于(变量b=0,i=0;b++
您可以使用查找所有行。它将只找到直线,没有曲线或圆。在查找线之前,可能需要运行边缘检测。下面是一个例子:


您可以找到opencv实现的示例。

我曾经有一个类似的图像处理问题,您可以阅读它。但是你基本上可以用同样的想法来处理任何你想处理的图像

基本数据如下所示:

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

我想你可能需要一个边缘过滤器。那个我不确定,对不起。希望其他人能提供帮助:)GIMP有很多开源的过滤器,看看它们这里有一个起点:你能限制这个问题吗?它必须处理透明度问题吗?不同颜色的线条?什么样的曲线-无?半圆?二次型?更复杂?那么任意的笔画怎么办,它能处理吗?它必须处理抗锯齿吗?而且,你真的需要对这么多的图像这样做吗?用Photoshop中的画笔工具来跟踪不是更快吗?我已经用更多的例子更新了我的答案,说明了如何处理数据。谢谢,我显然知道如何做,我只是没有一个逻辑集来将像素读取为*行。实际上我也在这样做。只是问一下,您是否使用了
buf8
?我没有,但添加了buf8说明,因为它可能会帮助您确定此技术工作正常吗?在这个演示中,有些线条没有被划过。它可以检测被划过的线条。但您可能需要调整参数以获得灵敏度。Hough变换将每个像素视为该像素所有方向上的一条势线。然后计算每个可能行的分数。如果在一条直线上设置的像素很少,那么这条直线将获得更多分数。通过设置阈值,您可以选择一行中要检测的最小像素数
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
    }
}
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