怎么用OPenCV编写一个程序把24位彩色图像转换为8位彩色图像?高分悬(50)赏求高人。5月31日急用。
下面是题目及要求(要是看不懂,上网翻译一下):Objective:Bytheendofthisassignmentyoushouldbefamiliarw...
下面是题目及要求(要是看不懂,上网翻译一下): Objective:
By the end of this assignment you should be familiar with the Color lookup and color compression techniques:
Assignment:
1. Write a program to transform a 24-bit color image into a 8-bit color image:
Divide the RGB cube into equal slices in each dimension. Shrink the R range and G range 0.. 255 into the 3-bit range 0.. 7 and shrink the B range down to the 2-bit range 0.. 3, making a total of 8 bits.
Test your implemented codes on the two 24-bit color images: lena.bmp and mandrill.bmp. Show the transformed 8-bit color images on your report.
2. Compute the 24-to-8 bit transformation errors for the above two methods on the two images. To describe the transformation error, the mean square error (MSE) is used and it is defined as:
where xn, yn, are the input data sequences, and N is the length of the data sequence.
麻烦发到邮箱:1085376241@qq.com 展开
By the end of this assignment you should be familiar with the Color lookup and color compression techniques:
Assignment:
1. Write a program to transform a 24-bit color image into a 8-bit color image:
Divide the RGB cube into equal slices in each dimension. Shrink the R range and G range 0.. 255 into the 3-bit range 0.. 7 and shrink the B range down to the 2-bit range 0.. 3, making a total of 8 bits.
Test your implemented codes on the two 24-bit color images: lena.bmp and mandrill.bmp. Show the transformed 8-bit color images on your report.
2. Compute the 24-to-8 bit transformation errors for the above two methods on the two images. To describe the transformation error, the mean square error (MSE) is used and it is defined as:
where xn, yn, are the input data sequences, and N is the length of the data sequence.
麻烦发到邮箱:1085376241@qq.com 展开
3个回答
展开全部
可以参考下面的程序,其中bitCount!=8 && bitCount!=24指的就是8位与24位
//BMP与IplImage相互转换
///////////////////////////////头文件bmp2ipl.h
//bmp2ipl.h
#ifndef BMP2IPL_H
#define BMP2IPL_H
class BMP {
public:
BMP():bmpData(NULL) {
memset(&biHeader, 0, sizeof(biHeader));
}
BMP(const BMP & img);
BMP(const IplImage &img);
BMP(int width, int height, int bitCount);
~BMP(){ delete [] bmpData; }
bool CreateImage(const BITMAPINFOHEADER &biHeader);
//Export
IplImage * BMP2Ipl();
//void Show(HWND hWnd, int nID);
//void Show(CDC *pDC, CRect & rect);
//void Show(HWND hWnd);
void ReSize(int newW, int newH);
private:
void CopyData(char *dest, const char *src, int dataByteSize,
bool isConvert, int height);
// isConvert=true 进行顶左和底左之间的转换(顶左到底左或底左到顶左),否则不转换
// biSizeImage may be set to zero for BI_RGB bitmaps, so calculate it.
int ImgSize() {
return ( biHeader.biHeight * ((biHeader.biWidth * biHeader.biBitCount / 8 + 3) & (-4)));
}
public:
void Clear();
BITMAPINFOHEADER biHeader;
unsigned char * bmpData;
};
#endif
/////////////////////////////////////////////////////////////////////实现文件bmp2ipl.cpp
#include "bmp2ipl.h"
/**************************************************************************************************
* *
* NOTE: *
* Only use the "8 bit, 1 or 3 channels" image, the BitMap use LowerLeft (底左), *
* the IplImage use TopLeft (顶左) *
* IplImage: *
* nChannels = 1 or 3 number of channels *
* depth = IPL_DEPTH_8U pixel depth (8 bit), IPL_DEPTH_8U=8 *
* dataOrder = 0 交叉存取颜色通道 *
* origin = IPL_ORIGIN_TL 图像数据保存形式,IPL_ORIGIN_BL底左结构, IPL_ORIGIN_TL顶左结构 *
* align = 4 行数据对齐方式,保证下一行数据从整4字节位置开始 *
* width *
* height *
* widthStep 图像数据行大小,单位字节 *
* imageSize 图像数据大小(=height*widthStep),单位字节 *
* imageData 指向图像数据区,char * *
* BITMAPINFOHEADER: *
* biSize Specifies the number of bytes required by the structure *
* biWidth *
* biHeight(>0) biHeight>0底左结构;biHeight<0顶左结构 *
* biPlanes = 1 Specifies the number of planes for the target device. This value *
* must be set to 1. *
* biBitCount =8 or 24 bits-per-pixel,8-(pixelDepth=8,channels=1), *
* 24-(pixelDepth=8,channels=3) *
* biCompression = BI_RGB An uncompressed format *
* biSizeImage Specifies the size, in bytes, of the image.This may be set to zero *
* for BI_RGB bitmaps. *
* biXPelsPerMeter = 0 *
* biYPelsPerMeter = 0 *
* biClrUsed = 0 *
* biClrImportant = 0 *
* *
***************************************************************************************************/
BMP::BMP(const BMP & img)
{
if(!IsSupport(img)) {
BMP();
return;
}
//biHeader = img.biHeader;
PBITMAPINFOHEADER pBmpH = (PBITMAPINFOHEADER)&img.biHeader;
memcpy(&biHeader, pBmpH, sizeof(BITMAPINFOHEADER));
biHeader.biSizeImage = ImgSize();
bool isLowerLeft = biHeader.biHeight>0;
//int rowSize=0;
if(!isLowerLeft) biHeader.biHeight=-biHeader.biHeight;
if(bmpData!=NULL) delete[] bmpData;
bmpData = new unsigned char [biHeader.biSizeImage];
//memcpy(bmpData, img.bmpData, img.biHeader.biSizeImage);
CopyData((char *)bmpData, (char*)img.bmpData, biHeader.biSizeImage,
!isLowerLeft, biHeader.biHeight);
}
BMP::BMP(const IplImage &img) {
if(!IsSupport(img)) {
BMP();
return;
}
bool isTopLeft = (img.origin == IPL_ORIGIN_TL);
biHeader.biSize = sizeof(BITMAPINFOHEADER);
biHeader.biWidth = img.width;
biHeader.biHeight = img.height;
biHeader.biPlanes = 1;
biHeader.biBitCount = img.depth * img.nChannels;
biHeader.biCompression = BI_RGB;
biHeader.biSizeImage = img.imageSize;
biHeader.biXPelsPerMeter = 0;
biHeader.biYPelsPerMeter = 0;
biHeader.biClrUsed = 0;
biHeader.biClrImportant = 0;
if(bmpData!=NULL) delete[] bmpData;
bmpData = new unsigned char [img.imageSize];
//memcpy(bmpData, img.ImageData, img.imageSize);
CopyData((char*)bmpData, (char*)img.imageData, img.imageSize,
isTopLeft, img.height);
/*int i,j;
CvScalar s;
for(i=0;i<img.width;i++)
for(j=0;j<img.height;j++){
s=cvGet2D(&img,i,j);
}
*/
}
BMP::BMP(int width, int height, int bitCount) {
if(bitCount!=8 && bitCount!=24) return;
biHeader.biSize = sizeof(BITMAPINFOHEADER);
biHeader.biWidth = width;
biHeader.biHeight = height;
biHeader.biPlanes = 1;
biHeader.biBitCount = bitCount;
biHeader.biCompression = BI_RGB;
biHeader.biSizeImage = ImgSize();
biHeader.biXPelsPerMeter = 0;
biHeader.biYPelsPerMeter = 0;
biHeader.biClrUsed = 0;
biHeader.biClrImportant = 0;
if(bmpData!=NULL) delete[] bmpData;
bmpData = new unsigned char [biHeader.biSizeImage];
Clear();
}
// dest: the destination image
// dataByteSize: the Source image
// height: source image height
void BMP::CopyData(char *dest, const char *src, int dataByteSize,
bool isConvert, int height) {
char * p = dest;
if(!isConvert) {
memcpy(dest, src, dataByteSize);
return;
}
if(height<=0) return;
//int height = dataByteSize/rowByteSize;
int rowByteSize = dataByteSize / height;
src = src + dataByteSize - rowByteSize ;
for(int i=0; i<height; i++) {
memcpy(dest, src, rowByteSize);
dest += rowByteSize;
src -= rowByteSize;
}
}
IplImage * BMP::BMP2Ipl() {
if(!IsSupport(*this)) return NULL;
IplImage *iplImg;
int height;
bool isLowerLeft = biHeader.biHeight>0;
height = (biHeader.biHeight>0) ? biHeader.biHeight : -biHeader.biHeight;
iplImg = cvCreateImage( cvSize(biHeader.biWidth, height), IPL_DEPTH_8U, biHeader.biBitCount / 8);
//iplImg = cvCreateImageHeader( cvSize(biHeader.biWidth, height), IPL_DEPTH_8U, biHeader.biBitCount / 8);
//cvSetData(iplImg,(char*)bmpData,biHeader.biSizeImage/height);
CopyData( iplImg->imageData, (char*)bmpData, biHeader.biSizeImage,
isLowerLeft, height);
/*int i,j;
CvScalar s;
int channels=biHeader.biBitCount / 8;
int step=(biHeader.biWidth*channels+3) & -4;
int loc=0;
for(i=0;i<iplImg->height;i++){
for(j=0;j<iplImg->width;j++){
loc=i*step + j*channels;
s.val[0]=bmpData[loc];
if(channels==3){
s.val[1]=bmpData[loc+1];
s.val[2]=bmpData[loc+2];
}
cvSet2D(iplImg,i,j,s);
}
}*/
return iplImg;
}
void BMP::Clear() {
if(bmpData == NULL) return;
memset(bmpData, 0, ImgSize());
}
void BMP::ReSize(int newW, int newH) {
biHeader.biWidth = newW;
biHeader.biHeight = newH;
biHeader.biSizeImage = ImgSize();
if(bmpData!=NULL) delete[] bmpData;
bmpData = new unsigned char [biHeader.biSizeImage];
Clear();
}
bool BMP::CreateImage(const BITMAPINFOHEADER &bih) {
memset(&biHeader,0,sizeof(BITMAPINFOHEADER));
delete[] bmpData;
bmpData = NULL;
memcpy(&biHeader, &bih, sizeof(BITMAPINFOHEADER));
biHeader.biSizeImage = ImgSize();
bmpData = new unsigned char [ biHeader.biSizeImage ];
if(bmpData == NULL) return false;
else{
Clear();
return true;
}
}
//BMP与IplImage相互转换
///////////////////////////////头文件bmp2ipl.h
//bmp2ipl.h
#ifndef BMP2IPL_H
#define BMP2IPL_H
class BMP {
public:
BMP():bmpData(NULL) {
memset(&biHeader, 0, sizeof(biHeader));
}
BMP(const BMP & img);
BMP(const IplImage &img);
BMP(int width, int height, int bitCount);
~BMP(){ delete [] bmpData; }
bool CreateImage(const BITMAPINFOHEADER &biHeader);
//Export
IplImage * BMP2Ipl();
//void Show(HWND hWnd, int nID);
//void Show(CDC *pDC, CRect & rect);
//void Show(HWND hWnd);
void ReSize(int newW, int newH);
private:
void CopyData(char *dest, const char *src, int dataByteSize,
bool isConvert, int height);
// isConvert=true 进行顶左和底左之间的转换(顶左到底左或底左到顶左),否则不转换
// biSizeImage may be set to zero for BI_RGB bitmaps, so calculate it.
int ImgSize() {
return ( biHeader.biHeight * ((biHeader.biWidth * biHeader.biBitCount / 8 + 3) & (-4)));
}
public:
void Clear();
BITMAPINFOHEADER biHeader;
unsigned char * bmpData;
};
#endif
/////////////////////////////////////////////////////////////////////实现文件bmp2ipl.cpp
#include "bmp2ipl.h"
/**************************************************************************************************
* *
* NOTE: *
* Only use the "8 bit, 1 or 3 channels" image, the BitMap use LowerLeft (底左), *
* the IplImage use TopLeft (顶左) *
* IplImage: *
* nChannels = 1 or 3 number of channels *
* depth = IPL_DEPTH_8U pixel depth (8 bit), IPL_DEPTH_8U=8 *
* dataOrder = 0 交叉存取颜色通道 *
* origin = IPL_ORIGIN_TL 图像数据保存形式,IPL_ORIGIN_BL底左结构, IPL_ORIGIN_TL顶左结构 *
* align = 4 行数据对齐方式,保证下一行数据从整4字节位置开始 *
* width *
* height *
* widthStep 图像数据行大小,单位字节 *
* imageSize 图像数据大小(=height*widthStep),单位字节 *
* imageData 指向图像数据区,char * *
* BITMAPINFOHEADER: *
* biSize Specifies the number of bytes required by the structure *
* biWidth *
* biHeight(>0) biHeight>0底左结构;biHeight<0顶左结构 *
* biPlanes = 1 Specifies the number of planes for the target device. This value *
* must be set to 1. *
* biBitCount =8 or 24 bits-per-pixel,8-(pixelDepth=8,channels=1), *
* 24-(pixelDepth=8,channels=3) *
* biCompression = BI_RGB An uncompressed format *
* biSizeImage Specifies the size, in bytes, of the image.This may be set to zero *
* for BI_RGB bitmaps. *
* biXPelsPerMeter = 0 *
* biYPelsPerMeter = 0 *
* biClrUsed = 0 *
* biClrImportant = 0 *
* *
***************************************************************************************************/
BMP::BMP(const BMP & img)
{
if(!IsSupport(img)) {
BMP();
return;
}
//biHeader = img.biHeader;
PBITMAPINFOHEADER pBmpH = (PBITMAPINFOHEADER)&img.biHeader;
memcpy(&biHeader, pBmpH, sizeof(BITMAPINFOHEADER));
biHeader.biSizeImage = ImgSize();
bool isLowerLeft = biHeader.biHeight>0;
//int rowSize=0;
if(!isLowerLeft) biHeader.biHeight=-biHeader.biHeight;
if(bmpData!=NULL) delete[] bmpData;
bmpData = new unsigned char [biHeader.biSizeImage];
//memcpy(bmpData, img.bmpData, img.biHeader.biSizeImage);
CopyData((char *)bmpData, (char*)img.bmpData, biHeader.biSizeImage,
!isLowerLeft, biHeader.biHeight);
}
BMP::BMP(const IplImage &img) {
if(!IsSupport(img)) {
BMP();
return;
}
bool isTopLeft = (img.origin == IPL_ORIGIN_TL);
biHeader.biSize = sizeof(BITMAPINFOHEADER);
biHeader.biWidth = img.width;
biHeader.biHeight = img.height;
biHeader.biPlanes = 1;
biHeader.biBitCount = img.depth * img.nChannels;
biHeader.biCompression = BI_RGB;
biHeader.biSizeImage = img.imageSize;
biHeader.biXPelsPerMeter = 0;
biHeader.biYPelsPerMeter = 0;
biHeader.biClrUsed = 0;
biHeader.biClrImportant = 0;
if(bmpData!=NULL) delete[] bmpData;
bmpData = new unsigned char [img.imageSize];
//memcpy(bmpData, img.ImageData, img.imageSize);
CopyData((char*)bmpData, (char*)img.imageData, img.imageSize,
isTopLeft, img.height);
/*int i,j;
CvScalar s;
for(i=0;i<img.width;i++)
for(j=0;j<img.height;j++){
s=cvGet2D(&img,i,j);
}
*/
}
BMP::BMP(int width, int height, int bitCount) {
if(bitCount!=8 && bitCount!=24) return;
biHeader.biSize = sizeof(BITMAPINFOHEADER);
biHeader.biWidth = width;
biHeader.biHeight = height;
biHeader.biPlanes = 1;
biHeader.biBitCount = bitCount;
biHeader.biCompression = BI_RGB;
biHeader.biSizeImage = ImgSize();
biHeader.biXPelsPerMeter = 0;
biHeader.biYPelsPerMeter = 0;
biHeader.biClrUsed = 0;
biHeader.biClrImportant = 0;
if(bmpData!=NULL) delete[] bmpData;
bmpData = new unsigned char [biHeader.biSizeImage];
Clear();
}
// dest: the destination image
// dataByteSize: the Source image
// height: source image height
void BMP::CopyData(char *dest, const char *src, int dataByteSize,
bool isConvert, int height) {
char * p = dest;
if(!isConvert) {
memcpy(dest, src, dataByteSize);
return;
}
if(height<=0) return;
//int height = dataByteSize/rowByteSize;
int rowByteSize = dataByteSize / height;
src = src + dataByteSize - rowByteSize ;
for(int i=0; i<height; i++) {
memcpy(dest, src, rowByteSize);
dest += rowByteSize;
src -= rowByteSize;
}
}
IplImage * BMP::BMP2Ipl() {
if(!IsSupport(*this)) return NULL;
IplImage *iplImg;
int height;
bool isLowerLeft = biHeader.biHeight>0;
height = (biHeader.biHeight>0) ? biHeader.biHeight : -biHeader.biHeight;
iplImg = cvCreateImage( cvSize(biHeader.biWidth, height), IPL_DEPTH_8U, biHeader.biBitCount / 8);
//iplImg = cvCreateImageHeader( cvSize(biHeader.biWidth, height), IPL_DEPTH_8U, biHeader.biBitCount / 8);
//cvSetData(iplImg,(char*)bmpData,biHeader.biSizeImage/height);
CopyData( iplImg->imageData, (char*)bmpData, biHeader.biSizeImage,
isLowerLeft, height);
/*int i,j;
CvScalar s;
int channels=biHeader.biBitCount / 8;
int step=(biHeader.biWidth*channels+3) & -4;
int loc=0;
for(i=0;i<iplImg->height;i++){
for(j=0;j<iplImg->width;j++){
loc=i*step + j*channels;
s.val[0]=bmpData[loc];
if(channels==3){
s.val[1]=bmpData[loc+1];
s.val[2]=bmpData[loc+2];
}
cvSet2D(iplImg,i,j,s);
}
}*/
return iplImg;
}
void BMP::Clear() {
if(bmpData == NULL) return;
memset(bmpData, 0, ImgSize());
}
void BMP::ReSize(int newW, int newH) {
biHeader.biWidth = newW;
biHeader.biHeight = newH;
biHeader.biSizeImage = ImgSize();
if(bmpData!=NULL) delete[] bmpData;
bmpData = new unsigned char [biHeader.biSizeImage];
Clear();
}
bool BMP::CreateImage(const BITMAPINFOHEADER &bih) {
memset(&biHeader,0,sizeof(BITMAPINFOHEADER));
delete[] bmpData;
bmpData = NULL;
memcpy(&biHeader, &bih, sizeof(BITMAPINFOHEADER));
biHeader.biSizeImage = ImgSize();
bmpData = new unsigned char [ biHeader.biSizeImage ];
if(bmpData == NULL) return false;
else{
Clear();
return true;
}
}
参考资料: http://www.opencv.org.cn/index.php/BMP%E4%B8%8EIplImage%E7%9B%B8%E4%BA%92%E8%BD%AC%E6%8D%A2
展开全部
int main()
{
char *grayName = "gray.jpg";
IplImage *srcImage = cvLoadImage("3.jpg",CV_LOAD_IMAGE_UNCHANGED);
IplImage *dstImage = cvCreateImage(cvSize(srcImage->width,srcImage->height),IPL_DEPTH_8U,1);
cvCvtColor(srcImage,dstImage,CV_RGB2GRAY);
cvSaveImage(grayName,dstImage);
return 0;
}
{
char *grayName = "gray.jpg";
IplImage *srcImage = cvLoadImage("3.jpg",CV_LOAD_IMAGE_UNCHANGED);
IplImage *dstImage = cvCreateImage(cvSize(srcImage->width,srcImage->height),IPL_DEPTH_8U,1);
cvCvtColor(srcImage,dstImage,CV_RGB2GRAY);
cvSaveImage(grayName,dstImage);
return 0;
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
以下资料可能会对你有所帮助,需要自己逐步摸索,要有耐心呀!!1在图像处理中,我们经常需要将真彩色图像转换为黑白图像。严格的讲应该是灰度图,因为真正的黑白图像是二色,即只有纯黑,纯白二色。开始之前,我们先简单补充一下计算机中图像的表示原理。计算机中的图像大致可以分成两类:位图和矢量图。位图可以视为一个二维的网格,整个图像就是由很多个点组成的,点的个数等于位图的宽乘以高。每个点被称为一个像素点,每个像素点有确定的颜色,当很多个像素合在一起时就形成了一幅完整的图像。我们通常使用的图像大部分都是位图,如数码相机拍摄的照片,都是位图。因为位图可以完美的表示图像的细节,能较好的还原图像的原景。但位图也有缺点:第一是体积比较大,所以人们开发了很多压缩图像格式来储存位图图像,目前应用最广的是JPEG格式,在WEB上得到了广泛应用,另外还有GIF,PNG等等。第二是位图在放大时,不可避免的会出现锯齿现象,这也由位图的本质特点决定的。所以在现实中,我们还需要使用到另一种图像格式:矢量图。同位图不同,矢量图同位图的原理不同,矢量图是利用数学公式通过圆,线段等绘制出来的,所以不管如何放大都不会出现变形,但矢量图不能描述非常复杂的图像。所以矢量图都是用来描述图形图案,各种CAD软件等等都是使用矢量格式来保存文件的。
在讲解颜色转换之前,我们要先对位图的颜色表示方式做一了解。位图中通常是用RGB三色方式来表示颜色的(位数很少时要使用调色板) 。所以每个像素采用不同的位数,就可以表示出不同数量的颜色。如下图所示:
每像素的位数
一个像素可分配到的颜色数量
2^1 =
2^2 =
2^4 = 1
2^8 = 25
1
2^16 = 65,53
2
2^24 = 16,777,21
从中我们可以看出,当使用2位色(个字节)时,我们可以得到1600多万种颜色,这已经非常丰富了,应该已接近人眼所能分辨的颜色了。现在计算机中使用最多的就是2位色,别外在GDI+中还有一种3位色,多出来的一个通道用来描述Alpha,即透明分量。
2位色中个字节分别用来描述R,G,B三种颜色分量,我们看到这其中是没有亮度分量的,这是因为在RGB表示方式中,亮度也是直接可以从颜色分量中得到的,每一颜色分量值的范围都是从0到255, 某一颜色分量的值越大,就表示这一分量的亮度值越高,所以25表示最亮,0表示最暗。那么一个真彩色像素点转换为灰度图时它的亮度值应该是多少呢,首先我们想到的平均值,即将R+G+B/。但现实中我们使用的却是如下的公式:
Y = 0.299R+0.587G+0.114B
这个公式通常都被称为心理学灰度公式。这里面我们看到绿色分量所占比重最大。因为科学家发现使用上述公式进行转换时所得到的灰度图最接近人眼对灰度图的感觉。
因为灰度图中颜色数量一共只有25种(个字节),所以转换后的图像我们通常保存为位格式而不是2位格式,这样比较节省空间。而位图像是使用调色板方式来保存颜色的。而不是直接保存颜色值。调色板中可以保存25颜色,所以可以正好可以将25种灰度颜色保存到调色版中。代码如下:
using System;using System.Collections.Generic;using System.Text;using System.Drawing;using System.Drawing.Imaging;namespace ConsoleApplication2}img.UnlockBits;bit.UnlockBits;ColorPalette palette = bit.Palette;for bit.Palette = palette;bit.Save;img.Dispose;bit.Dispose;}}}
代码中我使用了指针直接操作位图数据,同样的操作要比使用GetPixel, SetPixel快非常多。我们要感谢微软在C#中保留了这一强有力的工具。
在讲解颜色转换之前,我们要先对位图的颜色表示方式做一了解。位图中通常是用RGB三色方式来表示颜色的(位数很少时要使用调色板) 。所以每个像素采用不同的位数,就可以表示出不同数量的颜色。如下图所示:
每像素的位数
一个像素可分配到的颜色数量
2^1 =
2^2 =
2^4 = 1
2^8 = 25
1
2^16 = 65,53
2
2^24 = 16,777,21
从中我们可以看出,当使用2位色(个字节)时,我们可以得到1600多万种颜色,这已经非常丰富了,应该已接近人眼所能分辨的颜色了。现在计算机中使用最多的就是2位色,别外在GDI+中还有一种3位色,多出来的一个通道用来描述Alpha,即透明分量。
2位色中个字节分别用来描述R,G,B三种颜色分量,我们看到这其中是没有亮度分量的,这是因为在RGB表示方式中,亮度也是直接可以从颜色分量中得到的,每一颜色分量值的范围都是从0到255, 某一颜色分量的值越大,就表示这一分量的亮度值越高,所以25表示最亮,0表示最暗。那么一个真彩色像素点转换为灰度图时它的亮度值应该是多少呢,首先我们想到的平均值,即将R+G+B/。但现实中我们使用的却是如下的公式:
Y = 0.299R+0.587G+0.114B
这个公式通常都被称为心理学灰度公式。这里面我们看到绿色分量所占比重最大。因为科学家发现使用上述公式进行转换时所得到的灰度图最接近人眼对灰度图的感觉。
因为灰度图中颜色数量一共只有25种(个字节),所以转换后的图像我们通常保存为位格式而不是2位格式,这样比较节省空间。而位图像是使用调色板方式来保存颜色的。而不是直接保存颜色值。调色板中可以保存25颜色,所以可以正好可以将25种灰度颜色保存到调色版中。代码如下:
using System;using System.Collections.Generic;using System.Text;using System.Drawing;using System.Drawing.Imaging;namespace ConsoleApplication2}img.UnlockBits;bit.UnlockBits;ColorPalette palette = bit.Palette;for bit.Palette = palette;bit.Save;img.Dispose;bit.Dispose;}}}
代码中我使用了指针直接操作位图数据,同样的操作要比使用GetPixel, SetPixel快非常多。我们要感谢微软在C#中保留了这一强有力的工具。
追问
能不能发给我一个完全的代码?
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询
广告 您可能关注的内容 |