使用最近邻放大图像
Posted
技术标签:
【中文标题】使用最近邻放大图像【英文标题】:Scaling up an image using nearest-neighbor 【发布时间】:2017-06-11 04:55:05 【问题描述】:我一直在尝试让我的程序放大图像。我在为我的缩放图像分配新空间时遇到了一些问题,但我认为它是固定的。我遇到的问题是,当我试图从我的临时内存持有者发回我的图像时,程序崩溃了。
加载的图片放在我的struct
Image
。像素被放置在
img->pixels
,高度为img->height
,宽度为img->width
。但是我不知道为什么当我将像素从我的tmp2
struct
转移到我的img
struct
时程序会崩溃,而当我做相反的事情时它不会崩溃。代码如下:
void makeBigger(Image *img, int scale)
Image *tmp2;
tmp2 = (Image*)malloc(sizeof(Image));
tmp2->height = img->height*scale;
tmp2->width = img->width*scale;
tmp2->pixels = (Pixel**)malloc(sizeof(Pixel*)*tmp2->height);
for (unsigned int i = 0; i < img->height; i++)
tmp2->pixels[i] = (Pixel*)malloc(sizeof(Pixel)*tmp2->width);
for (unsigned int j = 0; j < img->width; j++)
tmp2->pixels[i][j] = img->pixels[i][j];
free(img->pixels);
//scaling up the struct's height and width
img->height *= scale;
img->width *= scale;
img->pixels = (Pixel**)malloc(sizeof(Pixel*)*img->height);
for (unsigned int i = 0; i < tmp2->height; i++)
img->pixels[i] = (Pixel*)malloc(sizeof(Pixel)*img->width);
for (unsigned int j = 0; j < tmp2->width; j++)
img->pixels[i][j] = tmp2->pixels[i+i/2][j+j/2];
如果您知道如何使最近邻方法起作用,我会很高兴。
编辑:我正在尝试裁剪内部矩形,以便将其放大(缩放)。
Image *tmp = (Image*)malloc(sizeof(Image));
tmp->height = img->height / 2;
tmp->width = img->width / 2;
tmp->pixels = (Pixel**)malloc(sizeof(Pixel*) * tmp->height);
for (unsigned i = img->height / 4 - 1; i < img->height - img->height / 4; i++)
tmp->pixels[i] = (Pixel*)malloc(sizeof(Pixel) * tmp->width);
for (unsigned j = img->width / 4; j < img->width - img->width / 4; j++)
tmp->pixels[i][j] = img->pixels[i][j];
for (unsigned i = 0; i < img->height; i++)
free(img->pixels[i]);
free(img->pixels);
img->height = tmp->height;
img->width = tmp->width;
img->pixels = tmp->pixels;
free(tmp);
【问题讨论】:
“程序崩溃”。调试此类问题的方法是使用调试器。 是的,我不确定它是关于什么的。似乎 tmp2->pixels 没有得到任何 RGB 值,这看起来很奇怪。但是,程序运行,我没有任何警告。 这就是调试器的用途!它允许您逐行遍历代码并检查变量以查看哪里出错了。 这显然会导致数组越界访问:img->pixels[i][j] = tmp2->pixels[i+i/2][j+j/2];
。
【参考方案1】:
我发现你把事情复杂化了(例如两次遍历图像)。这是代码(我发布了整个程序 - 我对 Pixel 和 图像可能与您所拥有的不匹配),但如果您复制/粘贴 makeBigger 它应该可以在您的代码中工作OOTB:
code00.c:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
typedef uint32_t Pixel;
typedef struct
uint32_t width, height;
Pixel **pixels;
Image;
void makeBigger(Image *img, int scale)
uint32_t i = 0, j = 0;
Image *tmp = (Image*)malloc(sizeof(Image));
tmp->height = img->height * scale;
tmp->width = img->width * scale;
tmp->pixels = (Pixel**)malloc(sizeof(Pixel*) * tmp->height);
for (i = 0; i < tmp->height; i++)
tmp->pixels[i] = (Pixel*)malloc(sizeof(Pixel) * tmp->width);
for (j = 0; j < tmp->width; j++)
tmp->pixels[i][j] = img->pixels[i / scale][j / scale];
for (i = 0; i < img->height; i++)
free(img->pixels[i]);
free(img->pixels);
img->width = tmp->width;
img->height = tmp->height;
img->pixels = tmp->pixels;
free(tmp);
void printImage(Image *img)
printf("Width: %d, Height: %d\n", img->width, img->height);
for (uint32_t i = 0; i < img->height; i++)
for (uint32_t j = 0; j < img->width; j++)
printf("%3d", img->pixels[i][j]);
printf("\n");
printf("\n");
int main()
uint32_t i = 0, j = 0, k = 1;
Image img;
// Initialize the image
img.height = 2;
img.width = 3;
img.pixels = (Pixel**)malloc(sizeof(Pixel*) * img.height);
for (i = 0; i < img.height; i++)
img.pixels[i] = (Pixel*)malloc(sizeof(Pixel) * img.width);
for (j = 0; j < img.width; j++)
img.pixels[i][j] = k++;
printImage(&img);
makeBigger(&img, 2);
printImage(&img);
// Destroy the image
for (i = 0; i < img.height; i++)
free(img.pixels[i]);
free(img.pixels);
printf("\nDone.\n");
return 0;
Notes(makeBigger 相关 - 旨在替换作为参数给出的图像内容):
构建一个临时图像作为放大图像 仅遍历临时图像一次(在我们分配像素时填充其像素);要保持对原始图像的缩放并确保将适当的像素“复制”到新图像中,只需将索引除以缩放因子:tmp->pixels[i][j] = img->pixels[i / scale][j / scale]
释放原始图像内容:因为每个像素行都是malloced,它也应该是freed(单独free(img->pixels);
会产生 内存泄漏)
存储临时图像内容(进入原始内容),然后释放它
输出:
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/***/q041861274]> ~/sopr.sh ### Set shorter prompt to better fit when pasted in *** (or other) pages ### [064bit prompt]> ls code00.c [064bit prompt]> gcc -o code00.exe code00.c [064bit prompt]> ./code00.exe Width: 3, Height: 2 1 2 3 4 5 6 Width: 6, Height: 4 1 1 2 2 3 3 1 1 2 2 3 3 4 4 5 5 6 6 4 4 5 5 6 6 Done.
【讨论】:
这完美无瑕。感谢您提供如此详细的答案!我希望其他人现在也可以从您的回答中获得帮助:) 哦,顺便说一句,我现在正在尝试放大图像。我的想法是我先从中间取一块,然后让它和原来的大小一样。但我不能得到中间的部分......你知道出了什么问题吗?我将编辑我的问题。 恐怕我不理解评论(我也没有看到对问题的任何编辑)。缩放是最近邻所做的(缩放因子>1为in,(0..1)为out)。如果您只想缩放图像的一部分,则必须传递其边界矩形,并且for
循环不会从 [0..height
/width
] 进行迭代, 但来自 [y1. . y2] / [x1..x2],其中 y 在 height
轴上,x 在 @ 987654329@一。
好的,谢谢。对此很抱歉,但我昨天很着急,显然我的编辑由于粘贴代码时出现错误而从未保存。但是,我确实尝试了该方法,但是当我尝试保存图像时出现了问题。
好的,所以我尝试裁剪图像,以便以后可以放大它。但我做不到。我在这里发布了代码。以上是关于使用最近邻放大图像的主要内容,如果未能解决你的问题,请参考以下文章
数字 0-9 的二进制图像的哪些特征应该与 k 最近邻算法一起使用?