C语言读取并显示灰度图像。
Read and display gray scale images in C language.
我想在C中加载灰度图像,对其进行预处理,然后显示修改后的图像。我的问题是:
C语言导入灰度图(jpeg,png格式)的正确方法是什么?
问这个问题之前我自己搜索的。
1- fread or with file management, we can read image but data will be encrypted(compressed), 我想要每个像素的灰度值(0-255).
2- 有一个 API ImageMagick 可能会有帮助,但它在 Mac OS X 上存在安装问题。
我用python和matlab做过图像处理,但对C语言一窍不通。
谢谢
您可以使用以下命令在 OS/X 上安装 ImageMagick:
sudo port install ImageMagick
获取 macports
包
对 Mac 没有太多经验,但我对 OpenCV 有很多了解。现在承认很多 OpenCV 是在 C++ 中(这可能是也可能不是问题)但是它绝对支持你想做的一切以及更多。它非常容易使用,有很多有用的 wiki 和一个非常好的社区。
Link 在 Mac 上安装:http://blogs.wcode.org/2014/10/howto-install-build-and-use-opencv-macosx-10-10/
Link 到一些 OpenCV 维基:http://opencv.org/documentation.html
编辑:
我还应该提到,旧版本的 OpenCV 在 C 中,如果您选择走 C 路线,仍然支持很多功能。
您有多种选择,但我将从最简单且与 OSX 集成度最低的选项开始,逐步与 OSX 集成度更高。
最简单的选择
就个人而言,如果我打算处理灰度图像,我会编写我的软件以使用 NetPBM 的便携式灰度图 (PGM) 格式,因为这是最简单的读取和写入格式,并且很容易与其他格式互换。没有压缩、DCT、量化、颜色spaces、EXIF 数据——只有您的数据带有简单的header。文档是 here.
PGM 文件基本上是这样的:
P2
# Shows the word "FEEP" (example from Netpbm man page on PGM)
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
您可以看到 P2
表示它是 ASCII(易于阅读)和灰度图。然后下一行说它是 24 像素宽 x 7 高,最亮的像素是 15。读写非常简单。您可以将 P2
更改为 P5
并以二进制形式在 MAXVAL 之后写入所有内容以保存 space.
现在您可以像这样在程序外部使用 ImageMagick 将 JPEG、PNG、GIF、TIFF 文件转换为 PGM - 无需任何链接或库或编译器开关:
convert input.png output.pgm
convert input.jpg output.pgm
同样,当您完成处理并以 PGM 格式创建生成的输出文件后,您可以通过简单地反转参数将其转换为 JPEG 或 TIFF:
convert result.pgm result.jpg
就个人而言,我会使用 homebrew
安装 ImageMagick。您转到 the homebrew website 并复制 one-liner 并将其粘贴到终端以安装 homebrew
。然后你可以安装 ImageMagick:
brew install imagemagick
顺便说一句,如果你想尝试这里的另一个建议,使用 OpenCV,那么就和
一样简单
brew search opencv
brew install homebrew/science/opencv
如果您想要一个小型的 self-contained OpenCV 项目示例,请查看我对另一个问题 here - you can also see how a project like that is possible from the command line with ImageMagick in my other answer 对同一问题的回答。
魔法++
如果您选择使用 homebrew
安装 ImageMagick,您将获得 Magick++,它允许您用 C 和 C++ 编写算法。它非常易于使用,并且可以 运行 在任何平台上使用,包括 OSX 和 Windows 以及 Linux 所以从这个角度来看它很有吸引力。它还内置了很多很多 image-processing 功能。有一个很好的教程 here, and documentation here.
您的代码将如下所示:
// Read an image from URL
Image url_image("http://www.serverName.com/image.gif");
// Read image from local filesystem
Image local_file_image("my_image.gif");
// Modify image
Pixels my_pixel_cache(my_image);
PixelPacket* pixels;
// define the view area that will be accessed via the image pixel cache
int start_x = 10, start_y = 20, size_x = 200, size_y = 100;
// return a pointer to the pixels of the defined pixel cache
pixels = my_pixel_cache.get(start_x, start_y, size_x, size_y);
// set the color of the first pixel from the pixel cache to black (x=10, y=20 on my_image)
*pixels = Color("black");
// set to green the pixel 200 from the pixel cache:
// this pixel is located at x=0, y=1 in the pixel cache (x=10, y=21 on my_image)
*(pixels+200) = Color("green");
// now that the operations on my_pixel_cache have been finalized
// ensure that the pixel cache is transferred back to my_image
my_pixel_cache.sync();
// Save results as BMP file
image.write(“result.bmp”);
Apple OSX 选项
另一个完全独立的选项是使用 Apple 提供的用于处理图像的工具 - 它们快速且易于使用,但不适用于 Linux 或 Windows。所以,例如,如果你想
a) 加载 PNG 文件(或 TIFF 或 JPEG,只需更改扩展名)
b) 将其保存为 JPEG 文件
c) 处理单个像素
// Load a PNG file
NSImage * strImage = [[NSImage alloc]initWithContentsOfFile:@"/Users/mark/Desktop/input.png"];
// Save NSImage as JPG
NSData *imageData = [strImage TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
imageData = [imageRep representationUsingType:NSJPEGFileType properties:imageProps];
[imageData writeToFile:@"/Users/Mark/Desktop/result.jpg" atomically:YES];
// Access individual pixels
int w=imageRep.pixelsWide;
int h=imageRep.pixelsHigh;
int bps=imageRep.bitsPerSample;
printf("Dimensions: %dx%d\n",w,h);
printf("bps: %d\n",bps);
// Get a pointer to the uncompressed, unencoded pixel data
unsigned char *pixelData = [imageRep bitmapData];
for(int j=0;j<10;j++){
printf("Pixel %d: %d\n",j,pixelData[j]);
}
当然,您可以采用上面的代码并轻松制作一个小实用程序,将任何文件格式转换为 PGM,然后您可以按照我的第一个建议使用 PGM 格式,而无需安装 ImageMagick - 尽管homebrew
.
实际上非常简单
请记住,您可以使用 clang(Apple 的编译器)在单个项目中将 Objective-C(如上例所示)与 C++ 和 C 混合使用,因此您可以继续使用 C,如您在你对我上面给出的任何例子的问题。
如果您不熟悉 OSX 上的开发,您需要前往 AppStore 免费下载 Apple 的 Xcode
以获得编译器和库。那你必须做
xcode-select --install
如果您希望使用 Makefile 和 command-line compilation/linking 进行传统开发,请安装 command-line 工具。
此答案试图演示如何使用 ImageMagick 的 MagickWand API 和 Xcode 进行开发,并且基于 OP 的评论。
安装 ImageMagick 后,启动一个新的 Xcode 命令行 C 项目。在编写任何代码之前,您需要告知 llvm 关于 ImageMagick resources/libraries/etc.
实现这一目标的方法有很多,但这是我能想到的最快的方法。
- 导航到顶级项目的“构建设置”
- 在 "All"(不是 "Basic")下搜索“Other Linker Flags”
- 在Xcode之外,打开Terminal.app并输入以下内容
MagickWand-config --ldflags
- 输入 Terminal.app 的输出作为“其他链接器标志”的值
- 返回设置搜索;输入“其他 C 标志”
- 回到Terminal.app运行以下
MagickWand-config --cflags
- 输入结果输出作为“其他 C 标志”的值
在文件 main.c
中,您应该注意到 Xcode 立即拾取 MagickWand 命令。
尝试以下操作(需要安装 X11)...
#include <stdio.h>
#include <wand/MagickWand.h>
int main(int argc, const char * argv[]) {
MagickWandGenesis();
MagickWand * wand;
wand = NewMagickWand();
MagickReadImage(wand, "wizard:");
MagickQuantizeImage(wand, 255, GRAYColorspace, 0, MagickFalse, MagickTrue);
MagickDisplayImage(wand, ":0");
wand = DestroyMagickWand(wand);
MagickWandTerminus();
return 0;
}
...并构建 + 运行 验证。
编辑
要获取每个像素的灰度 (0-255) 值,您可以调用像素迭代器(请参阅 second example here), or export the values。这是一个通过导出动态填充灰度值列表的示例。 .
// Get image size from wand instance
size_t width = MagickGetImageWidth(wand);
size_t height = MagickGetImageHeight(wand);
size_t total_gray_pixels = width * height;
// Allocate memory to hold values (total pixels * size of data type)
unsigned char * blob = malloc(total_gray_pixels);
MagickExportImagePixels(wand, // Image instance
0, // Start X
0, // Start Y
width, // End X
height, // End Y
"I", // Value where "I" = intensity = gray value
CharPixel, // Storage type where "unsigned char == (0 ~ 255)
blob); // Destination pointer
// Dump to stdout
for (int i = 0; i < total_gray_pixels; i++ ) {
printf("Gray value @ %lux%lu = %d\n", i % width, i / height, (int)blob[i]);
}
/** Example output...
* Gray value @ 0x0 = 226
* Gray value @ 1x0 = 189
* Gray value @ 2x0 = 153
* Gray value @ 3x0 = 116
* Gray value @ 4x0 = 80
* ... etc
*/
我想在C中加载灰度图像,对其进行预处理,然后显示修改后的图像。我的问题是:
C语言导入灰度图(jpeg,png格式)的正确方法是什么?
问这个问题之前我自己搜索的。
1- fread or with file management, we can read image but data will be encrypted(compressed), 我想要每个像素的灰度值(0-255).
2- 有一个 API ImageMagick 可能会有帮助,但它在 Mac OS X 上存在安装问题。
我用python和matlab做过图像处理,但对C语言一窍不通。
谢谢
您可以使用以下命令在 OS/X 上安装 ImageMagick:
sudo port install ImageMagick
获取 macports
包
对 Mac 没有太多经验,但我对 OpenCV 有很多了解。现在承认很多 OpenCV 是在 C++ 中(这可能是也可能不是问题)但是它绝对支持你想做的一切以及更多。它非常容易使用,有很多有用的 wiki 和一个非常好的社区。
Link 在 Mac 上安装:http://blogs.wcode.org/2014/10/howto-install-build-and-use-opencv-macosx-10-10/
Link 到一些 OpenCV 维基:http://opencv.org/documentation.html
编辑: 我还应该提到,旧版本的 OpenCV 在 C 中,如果您选择走 C 路线,仍然支持很多功能。
您有多种选择,但我将从最简单且与 OSX 集成度最低的选项开始,逐步与 OSX 集成度更高。
最简单的选择
就个人而言,如果我打算处理灰度图像,我会编写我的软件以使用 NetPBM 的便携式灰度图 (PGM) 格式,因为这是最简单的读取和写入格式,并且很容易与其他格式互换。没有压缩、DCT、量化、颜色spaces、EXIF 数据——只有您的数据带有简单的header。文档是 here.
PGM 文件基本上是这样的:
P2
# Shows the word "FEEP" (example from Netpbm man page on PGM)
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
您可以看到 P2
表示它是 ASCII(易于阅读)和灰度图。然后下一行说它是 24 像素宽 x 7 高,最亮的像素是 15。读写非常简单。您可以将 P2
更改为 P5
并以二进制形式在 MAXVAL 之后写入所有内容以保存 space.
现在您可以像这样在程序外部使用 ImageMagick 将 JPEG、PNG、GIF、TIFF 文件转换为 PGM - 无需任何链接或库或编译器开关:
convert input.png output.pgm
convert input.jpg output.pgm
同样,当您完成处理并以 PGM 格式创建生成的输出文件后,您可以通过简单地反转参数将其转换为 JPEG 或 TIFF:
convert result.pgm result.jpg
就个人而言,我会使用 homebrew
安装 ImageMagick。您转到 the homebrew website 并复制 one-liner 并将其粘贴到终端以安装 homebrew
。然后你可以安装 ImageMagick:
brew install imagemagick
顺便说一句,如果你想尝试这里的另一个建议,使用 OpenCV,那么就和
一样简单brew search opencv
brew install homebrew/science/opencv
如果您想要一个小型的 self-contained OpenCV 项目示例,请查看我对另一个问题 here - you can also see how a project like that is possible from the command line with ImageMagick in my other answer 对同一问题的回答。
魔法++
如果您选择使用 homebrew
安装 ImageMagick,您将获得 Magick++,它允许您用 C 和 C++ 编写算法。它非常易于使用,并且可以 运行 在任何平台上使用,包括 OSX 和 Windows 以及 Linux 所以从这个角度来看它很有吸引力。它还内置了很多很多 image-processing 功能。有一个很好的教程 here, and documentation here.
您的代码将如下所示:
// Read an image from URL
Image url_image("http://www.serverName.com/image.gif");
// Read image from local filesystem
Image local_file_image("my_image.gif");
// Modify image
Pixels my_pixel_cache(my_image);
PixelPacket* pixels;
// define the view area that will be accessed via the image pixel cache
int start_x = 10, start_y = 20, size_x = 200, size_y = 100;
// return a pointer to the pixels of the defined pixel cache
pixels = my_pixel_cache.get(start_x, start_y, size_x, size_y);
// set the color of the first pixel from the pixel cache to black (x=10, y=20 on my_image)
*pixels = Color("black");
// set to green the pixel 200 from the pixel cache:
// this pixel is located at x=0, y=1 in the pixel cache (x=10, y=21 on my_image)
*(pixels+200) = Color("green");
// now that the operations on my_pixel_cache have been finalized
// ensure that the pixel cache is transferred back to my_image
my_pixel_cache.sync();
// Save results as BMP file
image.write(“result.bmp”);
Apple OSX 选项
另一个完全独立的选项是使用 Apple 提供的用于处理图像的工具 - 它们快速且易于使用,但不适用于 Linux 或 Windows。所以,例如,如果你想
a) 加载 PNG 文件(或 TIFF 或 JPEG,只需更改扩展名)
b) 将其保存为 JPEG 文件
c) 处理单个像素
// Load a PNG file
NSImage * strImage = [[NSImage alloc]initWithContentsOfFile:@"/Users/mark/Desktop/input.png"];
// Save NSImage as JPG
NSData *imageData = [strImage TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
imageData = [imageRep representationUsingType:NSJPEGFileType properties:imageProps];
[imageData writeToFile:@"/Users/Mark/Desktop/result.jpg" atomically:YES];
// Access individual pixels
int w=imageRep.pixelsWide;
int h=imageRep.pixelsHigh;
int bps=imageRep.bitsPerSample;
printf("Dimensions: %dx%d\n",w,h);
printf("bps: %d\n",bps);
// Get a pointer to the uncompressed, unencoded pixel data
unsigned char *pixelData = [imageRep bitmapData];
for(int j=0;j<10;j++){
printf("Pixel %d: %d\n",j,pixelData[j]);
}
当然,您可以采用上面的代码并轻松制作一个小实用程序,将任何文件格式转换为 PGM,然后您可以按照我的第一个建议使用 PGM 格式,而无需安装 ImageMagick - 尽管homebrew
.
请记住,您可以使用 clang(Apple 的编译器)在单个项目中将 Objective-C(如上例所示)与 C++ 和 C 混合使用,因此您可以继续使用 C,如您在你对我上面给出的任何例子的问题。
如果您不熟悉 OSX 上的开发,您需要前往 AppStore 免费下载 Apple 的 Xcode
以获得编译器和库。那你必须做
xcode-select --install
如果您希望使用 Makefile 和 command-line compilation/linking 进行传统开发,请安装 command-line 工具。
此答案试图演示如何使用 ImageMagick 的 MagickWand API 和 Xcode 进行开发,并且基于 OP 的评论。
安装 ImageMagick 后,启动一个新的 Xcode 命令行 C 项目。在编写任何代码之前,您需要告知 llvm 关于 ImageMagick resources/libraries/etc.
实现这一目标的方法有很多,但这是我能想到的最快的方法。
- 导航到顶级项目的“构建设置”
- 在 "All"(不是 "Basic")下搜索“Other Linker Flags”
- 在Xcode之外,打开Terminal.app并输入以下内容
MagickWand-config --ldflags
- 输入 Terminal.app 的输出作为“其他链接器标志”的值
- 返回设置搜索;输入“其他 C 标志”
- 回到Terminal.app运行以下
MagickWand-config --cflags
- 输入结果输出作为“其他 C 标志”的值
在文件 main.c
中,您应该注意到 Xcode 立即拾取 MagickWand 命令。
尝试以下操作(需要安装 X11)...
#include <stdio.h>
#include <wand/MagickWand.h>
int main(int argc, const char * argv[]) {
MagickWandGenesis();
MagickWand * wand;
wand = NewMagickWand();
MagickReadImage(wand, "wizard:");
MagickQuantizeImage(wand, 255, GRAYColorspace, 0, MagickFalse, MagickTrue);
MagickDisplayImage(wand, ":0");
wand = DestroyMagickWand(wand);
MagickWandTerminus();
return 0;
}
...并构建 + 运行 验证。
编辑
要获取每个像素的灰度 (0-255) 值,您可以调用像素迭代器(请参阅 second example here), or export the values。这是一个通过导出动态填充灰度值列表的示例。 .
// Get image size from wand instance
size_t width = MagickGetImageWidth(wand);
size_t height = MagickGetImageHeight(wand);
size_t total_gray_pixels = width * height;
// Allocate memory to hold values (total pixels * size of data type)
unsigned char * blob = malloc(total_gray_pixels);
MagickExportImagePixels(wand, // Image instance
0, // Start X
0, // Start Y
width, // End X
height, // End Y
"I", // Value where "I" = intensity = gray value
CharPixel, // Storage type where "unsigned char == (0 ~ 255)
blob); // Destination pointer
// Dump to stdout
for (int i = 0; i < total_gray_pixels; i++ ) {
printf("Gray value @ %lux%lu = %d\n", i % width, i / height, (int)blob[i]);
}
/** Example output...
* Gray value @ 0x0 = 226
* Gray value @ 1x0 = 189
* Gray value @ 2x0 = 153
* Gray value @ 3x0 = 116
* Gray value @ 4x0 = 80
* ... etc
*/