如何在编写侵蚀过滤器时正确创建循环?
How can I create the loop properly while writing erosion filter?
我正在尝试编写侵蚀 filter.I 尝试确定我更改的部分,但我想填充其他数组元素 255.How 我可以这样做吗?
public static byte[] dnmmmerosion(byte[] data)
{
int wdth = 2400;
int hght = 800;
List<byte> dnmbytee = new List<byte>();
byte[] dnmbyte = new byte[1200000];
for (int i = 0; i < 1200000; i++)
{
dnmbytee[i] = 255;
}
for (int k = 1; k < hght-1; k++)
{
for (int vvv = 0; vvv < wdth-1; vvv++)
{
if (data[k+vvv] == 0 && data[k *wdth+vvv] == 0)
{
if (data[k * wdth + (vvv+1)] == 0 && data[k * wdth + vvv+2] == 0)
{
if (data[(k + 1) * wdth + vvv] == 0)
{
dnmbytee[k * wdth + vvv+1] = 0;
}
}
}
}
}
for (int zzz = 0; zzz < 1200000; zzz++)
{
dnmbyte[zzz] = dnmbytee[zzz];
}
return dnmbyte;
}
我的意思是我填充的元素在上面(比如:data[k+vvv] == 0,...)我想我在创建循环时在系数方面犯了错误
PS:我这样写代码的时候看到的画面很呆板
我正在对二进制图像进行处理。(因此数组由 255 和 0 元素组成。)如果结构的元素与图像中的元素相同(例如 elements:1,2,3 ,4,5) 将 255 写入第 3 个元素。
我不懂 C#,所以不会在代码中解决一些我不理解的问题。
首先你设置
int wdth = 2400;
int hght = 800;
然后为输出缓冲区分配 1,200,000 字节。这意味着您循环了 2400 x 800 = 1,920,000 字节,这大大超出了您的缓冲区。我认为您打算改为设置 hght = 500
。为避免此类问题,请不要多次使用相同的数值,而是定义可在代码中使用的常量:
int channels = 3;
int width = 800; // let's not be lazy, and use real words as variable names!
int height = 500;
int buffer_size = channels * width * height;
byte[] dnmbyte = new byte[buffer_size];
for (int i = 0; i < buffer_size; i++)
...
接下来,我不确定为什么你需要中间缓冲区dnmbytee
,为什么你不能直接写入dnmbyte
。不知道 C# 中的 List
是什么,我假设它不是一个数组,而是一个实际的列表数据结构。像你这样使用它会非常昂贵,请坚持使用数组来获取像素数据!
最后,主要问题:您正在访问缓冲区,就好像您有 2400 x 500 像素,每个像素一个字节,而不是 800 x 500 像素,每个像素三个字节 (RGB)。形态学操作在彩色图像上没有很好的定义,所以我在这里假设一个像素的所有三个字节总是相同的。如果是,则读取每个像素的第一个字节,并写入所有三个字节。
为此,您将像这样循环和索引:
for (int y = 1; y < height-1; y++) { // loop over all rows except the top and bottom-most ones
for (int x = 1; x < width-1; x++) { // loop over all columns, except the left and right-most ones
int current_pixel_index = (y * width + x) * channels;
// read at data[current_pixel_index]
...
dnmbyte[current_pixel_index + 0] = 0;
dnmbyte[current_pixel_index + 1] = 0;
dnmbyte[current_pixel_index + 2] = 0;
}
}
要访问相邻像素,您始终将相同的值添加到当前像素索引:channels
使像素位于右侧,-width*channels
使像素位于顶部,等等。为结构元素中的每个像素创建一个列表,然后遍历该列表:
int[5] neighbors;
neighbors[0] = -width*channels;
neighbors[1] = -channels;
neighbors[2] = 0;
neighbors[3] = +channels;
neighbors[4] = +width*channels;
for (int y = 1; y < height-1; y++) {
for (int x = 1; x < width-1; x++) {
int current_pixel_index = (y * width + x) * channels;
for (int k = 0; k < 5; k++) {
// read at data[current_pixel_index + neighbors[k]]
}
}
}
腐蚀逻辑可以是这样的:
for (int k = 0; k < 5; k++) {
if (data[current_pixel_index + neighbors[k]] == 0) {
dnmbyte[current_pixel_index + 0] = 0;
dnmbyte[current_pixel_index + 1] = 0;
dnmbyte[current_pixel_index + 2] = 0;
break;
}
}
由于输出数组初始化为 255,如果 none 个邻居为 0,它将保持该值。
上面的代码没有设置图像边缘的任何像素(第一行和最后一行和列)。如果你也想处理这些,最简单的方法是在所有边上用一个像素填充输入,新像素的值应该为 255。另一种方法是在边缘像素处进行特殊处理,确保你不要试图越界读取。这种类型的处理往往会大大降低代码速度,也会使代码复杂化。填充通常是值得的!
我正在尝试编写侵蚀 filter.I 尝试确定我更改的部分,但我想填充其他数组元素 255.How 我可以这样做吗?
public static byte[] dnmmmerosion(byte[] data)
{
int wdth = 2400;
int hght = 800;
List<byte> dnmbytee = new List<byte>();
byte[] dnmbyte = new byte[1200000];
for (int i = 0; i < 1200000; i++)
{
dnmbytee[i] = 255;
}
for (int k = 1; k < hght-1; k++)
{
for (int vvv = 0; vvv < wdth-1; vvv++)
{
if (data[k+vvv] == 0 && data[k *wdth+vvv] == 0)
{
if (data[k * wdth + (vvv+1)] == 0 && data[k * wdth + vvv+2] == 0)
{
if (data[(k + 1) * wdth + vvv] == 0)
{
dnmbytee[k * wdth + vvv+1] = 0;
}
}
}
}
}
for (int zzz = 0; zzz < 1200000; zzz++)
{
dnmbyte[zzz] = dnmbytee[zzz];
}
return dnmbyte;
}
我的意思是我填充的元素在上面(比如:data[k+vvv] == 0,...)我想我在创建循环时在系数方面犯了错误
PS:我这样写代码的时候看到的画面很呆板
我正在对二进制图像进行处理。(因此数组由 255 和 0 元素组成。)如果结构的元素与图像中的元素相同(例如 elements:1,2,3 ,4,5) 将 255 写入第 3 个元素。
我不懂 C#,所以不会在代码中解决一些我不理解的问题。
首先你设置
int wdth = 2400;
int hght = 800;
然后为输出缓冲区分配 1,200,000 字节。这意味着您循环了 2400 x 800 = 1,920,000 字节,这大大超出了您的缓冲区。我认为您打算改为设置 hght = 500
。为避免此类问题,请不要多次使用相同的数值,而是定义可在代码中使用的常量:
int channels = 3;
int width = 800; // let's not be lazy, and use real words as variable names!
int height = 500;
int buffer_size = channels * width * height;
byte[] dnmbyte = new byte[buffer_size];
for (int i = 0; i < buffer_size; i++)
...
接下来,我不确定为什么你需要中间缓冲区dnmbytee
,为什么你不能直接写入dnmbyte
。不知道 C# 中的 List
是什么,我假设它不是一个数组,而是一个实际的列表数据结构。像你这样使用它会非常昂贵,请坚持使用数组来获取像素数据!
最后,主要问题:您正在访问缓冲区,就好像您有 2400 x 500 像素,每个像素一个字节,而不是 800 x 500 像素,每个像素三个字节 (RGB)。形态学操作在彩色图像上没有很好的定义,所以我在这里假设一个像素的所有三个字节总是相同的。如果是,则读取每个像素的第一个字节,并写入所有三个字节。
为此,您将像这样循环和索引:
for (int y = 1; y < height-1; y++) { // loop over all rows except the top and bottom-most ones
for (int x = 1; x < width-1; x++) { // loop over all columns, except the left and right-most ones
int current_pixel_index = (y * width + x) * channels;
// read at data[current_pixel_index]
...
dnmbyte[current_pixel_index + 0] = 0;
dnmbyte[current_pixel_index + 1] = 0;
dnmbyte[current_pixel_index + 2] = 0;
}
}
要访问相邻像素,您始终将相同的值添加到当前像素索引:channels
使像素位于右侧,-width*channels
使像素位于顶部,等等。为结构元素中的每个像素创建一个列表,然后遍历该列表:
int[5] neighbors;
neighbors[0] = -width*channels;
neighbors[1] = -channels;
neighbors[2] = 0;
neighbors[3] = +channels;
neighbors[4] = +width*channels;
for (int y = 1; y < height-1; y++) {
for (int x = 1; x < width-1; x++) {
int current_pixel_index = (y * width + x) * channels;
for (int k = 0; k < 5; k++) {
// read at data[current_pixel_index + neighbors[k]]
}
}
}
腐蚀逻辑可以是这样的:
for (int k = 0; k < 5; k++) {
if (data[current_pixel_index + neighbors[k]] == 0) {
dnmbyte[current_pixel_index + 0] = 0;
dnmbyte[current_pixel_index + 1] = 0;
dnmbyte[current_pixel_index + 2] = 0;
break;
}
}
由于输出数组初始化为 255,如果 none 个邻居为 0,它将保持该值。
上面的代码没有设置图像边缘的任何像素(第一行和最后一行和列)。如果你也想处理这些,最简单的方法是在所有边上用一个像素填充输入,新像素的值应该为 255。另一种方法是在边缘像素处进行特殊处理,确保你不要试图越界读取。这种类型的处理往往会大大降低代码速度,也会使代码复杂化。填充通常是值得的!