24位真彩色转换为8位灰度图片(完整代码)
- 格式:doc
- 大小:686.00 KB
- 文档页数:23
灰度变换代码
以下是一个简单的灰度变换代码示例,该代码将图像的每个像素的灰度值提高50:
```python
import cv2
# 加载图像
img = cv2.imread('image.png', 0)
# 遍历图像的每个像素,将其灰度值增加50
h, w = img.shape
for i in range(h):
for j in range(w):
img[i, j] = img[i, j] + 50
# 显示修改后的图像
cv2.imshow('modified image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
在上述代码中,`cv2.imread()`函数用于加载图像。
第二个参数`0`表示将图像读取为灰度图像。
如果不指定该参数,则默认读取为彩色图像。
然后使用两个嵌套的循环遍历每个像素,并将其灰度值增加50。
最后使用`cv2.imshow()`函数显示图像,并使用`cv2.waitKey()`函数等待按下任意键退出程序。
`cv2.destroyAllWindows()`函数用于关闭生成的所有窗口。
灰度处理器函数详解1. 灰度处理器函数的定义和用途灰度处理器函数是一种用于将彩色图像转换为灰度图像的函数。
在计算机视觉和图像处理中,灰度处理是一种常见的预处理步骤,对于识别、分析和处理图像中的特征非常有帮助。
彩色图像是由红(R)、绿(G)和蓝(B)三个颜色通道组成的,每个通道的像素值范围是0-255。
而灰度图像只有一个颜色通道,每个像素的值范围也是0-255,代表了图像的亮度。
灰度处理器函数通过将每个像素的RGB值转换为灰度值来实现转换。
具体的灰度计算方法有多种,其中最常见的方法是将RGB值按照一定权重相加或者取平均值。
通过灰度处理,我们可以将彩色图像转换为灰度图像,便于后续的处理和分析。
2. 灰度处理器函数的工作方式下面是一个示例的灰度处理器函数的代码:def grayscale(image):width, height = image.sizegrayscale_image = Image.new("L", (width, height))for y in range(height):for x in range(width):pixel = image.getpixel((x, y))red, green, blue = pixel[0], pixel[1], pixel[2]gray_value = int(0.2989 * red + 0.587 * green + 0.114 * blue)grayscale_image.putpixel((x, y), gray_value)return grayscale_image这个函数接收一个彩色图像作为输入,返回一个灰度图像。
函数内部使用了PIL库(Python Imaging Library)来进行图像处理操作。
函数首先获取图像的宽度和高度,然后创建一个新的灰度图像对象,尺寸与输入图像一致。
接下来,函数使用两个嵌套的循环遍历输入图像的每个像素。
PythonPIL彩⾊图像转灰度图像1. PIL彩⾊图像转灰度图像 PIL彩⾊图像转灰度图像只需要调⽤函数 transforms.Grayscale(1) 即可。
需要注意的是PIL打开的图像是RGB格式的,⼀般是三通道,转为灰度图像后,变为⼀通道。
转换原理,采⽤的 ITU-R 601-2 luma 原理来转换的,L = R * 299/1000 + G * 587/1000 + B * 114/1000,下取整,⼩数被省略,跟OpenCV有区别,OpenCV保留⼩数位。
⼩⽣就不多⾔了,客官请下观~~。
2. 例⼦2.1 Code1import numpy as np2import torchvision.transforms as transforms3from PIL import Image456def image_RGB2Gray():7# 图⽚路径,相对路径8 image_path = "./fusion_datasets/1.jpg"9# 读取图⽚10 image = Image.open(image_path)11# 输出维度12print("RGB图像的维度:", np.array(image).shape)13# 显⽰原图14 image.show()15# RGB转换我灰度图像16 image_transforms = pose([17 transforms.Grayscale(1)18 ])19 image = image_transforms(image)20# 输出灰度图像的维度21print("灰度图像维度: ", np.array(image).shape)22# 显⽰灰度图像23 image.show()242526if__name__ == '__main__':27 image_RGB2Gray()2.2 结果显⽰ 转换前后的维度变换,开始是3通道的(height, width, channel),转为灰度图像后维度为1通道,1被省略显⽰。
彩色图像转灰度图像L=imread('i:\1.jpg')L=double(L);Xrgb=0.2990*L(:,:,1)+0.5870*L(:,:,2)+0.1140*L(:,:,3); NbColors=255;X=wcodemat(Xrgb,NbColors);map1=gray(NbColors);image(X);colormap(map1);title('原图像的灰度图');小波压缩-低频信息保留压缩方式L=imread('i:\1.jpg')L=double(L);Xrgb=0.2990*L(:,:,1)+0.5870*L(:,:,2)+0.1140*L(:,:,3); NbColors=255;X=wcodemat(Xrgb,NbColors);map1=gray(NbColors);image(X);colormap(map1);title('原图像的灰度图');axis square;disp('灰度图像X的大小');whos('X')[c,s]=wavedec2(X,2,'bior3.7');ca1=appcoef2(c,s,'bior3.7',1);ch1=detcoef2('h',c,s,1);%水平方向cv1=detcoef2('v',c,s,1);%垂直方向cd1=detcoef2('d',c,s,1);%斜线方向a1=wrcoef2('a',c,s,'bior3.7',1);h1=wrcoef2('h',c,s,'bior3.7',1);v1=wrcoef2('v',c,s,'bior3.7',1);d1=wrcoef2('d',c,s,'bior3.7',1);%各频率成分重构c1=[a1,h1;v1,d1];image(c1);colormap(gray);axis square;title('分解后低频和高频信息');ca1=appcoef2(c,s,'bior3.7',1);ca1=wcodemat(ca1,440,'mat',0);ca1=0.5*ca1;disp('第一次压缩后图像的大小为:');image(ca1);colormap(gray);%colormap(map);axis square;title('第一次压缩图像');whos('ca1')ca2=appcoef2(c,s,'bior3.7',2);ca2=0.25*ca2;image(ca2);colormap(gray);%colormap(map);axis square;title('第二次压缩图像');disp('第二次压缩后图像大小为:');whos('ca2')灰度图像X 的大小Name Size Bytes ClassX 150x125 150000 double arrayGrand total is 18750 elements using 150000 bytes第一次压缩后图像的大小为:Name Size Bytes Classca1 82x70 45920 double array Grand total is 5740 elements using 45920 bytes第二次压缩后图像大小为:Name Size Bytes Classca2 48x42 16128 double array Grand total is 2016 elements using 16128 bytes二维小波压缩H=imread('i:\1.jpg')H=double(H);Grgb=0.2990*H(:,:,1)+0.5870*H(:,:,2)+0.1140*H(:,:,3); NbColors=255;G=wcodemat(Grgb,NbColors);map2=gray(NbColors);figure(4);image(G);colormap(map2);title('原图像的灰度图');%转换成为灰度级索引图像[CA1,CH1,CV1,CD1]=dwt2(G,'bior3.7');%从分解系数中提取近似和细节[CA1,CH1,CV1,CD1]=dwt2(G,'bior3.7');A1=upcoef2('a',CA1,'bior3.7',1);H1=upcoef2('h',CH1,'bior3.7',1);V1=upcoef2('v',CV1,'bior3.7',1);D1=upcoef2('d',CD1,'bior3.7',1);%显示近似和细节%figure (' name ','近似分量A1');colormap(map2);subplot(2,2,1);image(wcodemat(A1,192));title('近似A1');subplot(2,2,2);image(wcodemat(H1,192));title('水平细节H1');subplot(2,2,3);image(wcodemat(V1,192));title('垂直细节V1');subplot(2,2,4);image(wcodemat(D1,192));title('对角细节D1');%对图像进行多尺度分解[C,S]=wavedec2(G,2,'bior3.7');%提取分解后的近似和细节系数CA2=appcoef2(C,S,'bior3.7',2);[CH2,CV2,CD2]=detcoef2('all',C,S,2);[CH1,CV1,CD1]=detcoef2('all',C,S,2);%从系数C重构第二层近似A2=wrcoef2('a',C,S,'bior3.7',2);H1=wrcoef2('h',C,S,'bior3.7',1);V1=wrcoef2('v',C,S,'bior3.7',1);D1=wrcoef2('d',C,S,'bior3.7',1);H2=wrcoef2('h',C,S,'bior3.7',2);V2=wrcoef2('v',C,S,'bior3.7',2);D2=wrcoef2('d',C,S,'bior3.7',2);%显示多尺度分解的结果%figure (' name ','多尺度分解后的近似与细节'); colormap(map2);subplot(2,4,1);image(wcodemat(A1,192));title('近似A1');subplot(2,4,2);image(wcodemat(H1,192));title('水平细节H1');subplot(2,4,3);image(wcodemat(V1,192));title('垂直细节V1');subplot(2,4,4);image(wcodemat(D1,192));title('对角细节D1');subplot(2,4,5);image(wcodemat(A2,192));title('近似A2');subplot(2,4,6);image(wcodemat(H2,192));title('水平细节H2');subplot(2,4,7);image(wcodemat(V2,192));title('垂直细节V2');subplot(2,4,8);image(wcodemat(D2,192));title('对角细节D2');%从多尺度分解后的系数重构原始图像并显示结果G0=waverec2(C,S,'bior3.7');%figure ('name','多尺度分解后的系数重构原始图像');image(G0);colormap(map2);colorbar;小波包压缩F=imread('i:\1.jpg')F=double(F);Ergb=0.2990*F(:,:,1)+0.5870*F(:,:,2)+0.1140*F(:,:,3);NbColors=255;E=wcodemat(Ergb,NbColors);map4=gray(NbColors);figure('name','小波包压缩');subplot(1,2,1);image(E);colormap(map4);title('原始图像');%==================================%采用默认的全局阈值进行图像压缩处理[thr,sorh,keepapp,crit]=ddencmp('cmp','wp',E);[Ec,treed,perf0,perfl2]=wpdencmp(E,sorh,3,'bior3.1',crit,thr,keepapp); subplot(1,2,2);image(Ec);colormap(map4);title('压缩后的图像');%==================================%给出压缩效率disp('小波分解系数中置0的系数个数百分比:'); perf0disp('压缩后图像剩余能量百分比:');perfl2小波分解系数中置0的系数个数百分比:perf0 =53.0851压缩后图像剩余能量百分比:perfl2 =99.9981DCT压缩x=imread('i:\1.jpg')I=rgb2gray(x);J=dct2(I);%figure('name','色图');imshow(log(abs(J)));colormap(jet(64));colorbar;J(abs(J)<10)=0;K=idct2(J)/255;%figure('name','DCT压缩的图像'); imshow(I);disp('DCT压缩的图像的大小:');whos('I')%figure('name','DCT压缩编码后的图像'); imshow(K);disp('DCT压缩编码后的图像的大小:'); whos('K')DCT压缩的灰度图像原图像的色图x=imread('i:\1.jpg')I=rgb2gray(x);J=dct2(I);%figure('name','色图');imshow(log(abs(J)));colormap(jet(64));colorbar;J(abs(J)<10)=0;K=idct2(J)/255;小波消噪A=imread('i:\1.jpg')A=double(A);Brgb=0.2990*A(:,:,1)+0.5870*A(:,:,2)+0.1140*A(:,:,3); NbColors=255;B=wcodemat(Brgb,NbColors);map3=gray(NbColors);figure('name','小波消噪处理')subplot(2,2,1);image(B);%colormap(map3);title('原始图像灰度图');axis square;%生成含噪图像并图示init=2055615866;randn('seed',init);BB=B+8*randn(size(B));subplot(2,2,2);image(BB);colormap(map3);title('含噪图像');axis square;%对图像进行消噪处理%用小波函数coif2对图像XX进行2层分解[cc,dd]=wavedec2(BB,2,'coif2');n=[1,2];%设置尺度向量p=[10.28,24.08];%设置阈值向量%对三个高频系数进行阈值处理nc=wthcoef2('h',cc,dd,n,p,'s');nc=wthcoef2('v',cc,dd,n,p,'s');nc=wthcoef2('d',cc,dd,n,p,'s');B1=waverec2(nc,dd,'coif2');subplot(2,2,3);image(B1);colormap(map3);title('第一次消噪后的图像');axis square;%再次对三个高频系数进行阈值处理mc=wthcoef2('h',nc,dd,n,p,'s');mc=wthcoef2('v',nc,dd,n,p,'s');mc=wthcoef2('d',nc,dd,n,p,'s');%对更新后的小波分解结构进行重构并图示结果B2=waverec2(mc,dd,'coif2');subplot(2,2,4);image(B2);colormap(map3);title('第二次消噪后的图像');axis square;。
24位bmp彩色图转换为24位灰度图的方法一、所用到的流处理函数:fstream:可同时进行读写操作的文件类;或ofstream:写操作(从内存中读数据到文件)的文件类;ifstream:读操作(从文件读数据到内存)的文件类。
二、位图文件的格式:①位图文件头,所用结构体:BITMAPFILEHEADER,占14个字节②位图信息头,所用结构体:BITMAPINFOHEADER,占40个字节③颜色表项,所用结构体:RGBQUAD,由biBitCount值决定④数据区,当结构体BITMAPINFOHEADER中的成员变量biBitCount = 1时,1个字节代表8个像素;biBitCount = 2时,1个字节代表2个像素;biBitCount = 8时,1个字节代表1个像素;biBitCount = 16时,2个字节代表1个像素;biBitCount = 24时,3个字节代表1个像素;RGBQUAD结构体的定义如下:typedef struct tagRGBQUAD {BYTE rgbBlue; // 蓝色分量BYTE rgbGreen; // 绿色分量BYTE rgbRed; // 红色分量BYTE rgbReserved; // 保留值,必须为0.} RGBQUAD;即一个RGBQUAD结构体占4个字节,当biBitCount = 1,2,4,8时,颜色表项分别占2,4,16,256个RGBQUAD 结构体大小的空间;当biBitCount = 24时,③颜色表项不占空间,即位图文件只有①②④三项,这是因为数据区中3个字节代表一个像素,本身含有三原色分量值。
三、需要注意的问题:1. bmp数据存储时按行从左到右、按列从下到上扫描,所以对于24位bmp 文件,数据区前三个字节代表位图左下角第一个元素;2. bmp文件存储的图片数据每行所占的字节数都是4的整数倍,不够的用0补充,所以有biSizeImage = ((((bi.Width*bitBitCount)+31)&~31)/8)*bi.biHeight3. 对于24位bmp文件,若图片每行像素所占字节数满足是4的整数倍这个条件,由于BITMAPFILEHEADER和BITMAPINFOHEADER所占的总字节数为54,不是4的倍数,所以补0后为56字节。
转载:OpenCV实现彩⾊图像转换为灰度图及⼆值化处理#include "stdafx.h"#include#include#include#includeusing namespace std;//声明图像IplImage指针IplImage* pSrcImg=NULL;IplImage* pGrayImg=NULL;IplImage* pBinaryImg=NULL;int Thresh=127;//初始化滑动条位置//滑动条响应函数void onTrackerSlid(int thresh){//将图像转化为⼆值图pBinaryImg=cvCreateImage(cvGetSize(pSrcImg),pSrcImg->depth,pSrcImg->nChannels);cvCopy(pSrcImg,pBinaryImg);//复制图像数据CvScalar scalar;int avg;for(int i=0;iheight;i++){for(int j=0;jwidth;j++){scalar=cvGet2D(pBinaryImg,i,j);//获取点(i,j)的像素avg=(scalar.val[0]+scalar.val[1]+scalar.val[2])/3;if(avg{scalar.val[0]=scalar.val[1]=scalar.val[2]=0;cvSet2D(pBinaryImg,i,j,scalar);}else{scalar.val[0]=scalar.val[1]=scalar.val[2]=255;cvSet2D(pBinaryImg,i,j,scalar);}}}//显⽰图像cvShowImage("⼆值化图像",pBinaryImg);}int main(int argc, char** argv){if(argc!=2)argv[1]="lena.jpg";//载⼊图像if((pSrcImg=cvLoadImage(argv[1],1))!=0){cout<<"按Esc键退出..."<<endl;//将颜⾊空间由RGB转化为GraypGrayImg=cvCreateImage(cvGetSize(pSrcImg),8,1);cvCvtColor(pSrcImg,pGrayImg,CV_RGB2GRAY);//创建图像窗⼝cvNamedWindow("原图像",CV_WINDOW_AUTOSIZE);cvNamedWindow("灰度图像",CV_WINDOW_AUTOSIZE);cvNamedWindow("⼆值化图像",CV_WINDOW_AUTOSIZE);//添加滑动条来调节阈值cvCreateTrackbar("阈值","⼆值化图像",&Thresh,255,onTrackerSlid); onTrackerSlid(Thresh);//显⽰图像cvShowImage("原图像",pSrcImg);cvShowImage("灰度图像",pGrayImg);//保存图像cvSaveImage("Gray_Image.jpg",pGrayImg);cvSaveImage("Binary_Image.jpg",pBinaryImg);//等待按"Esc"键退出while(true)if(cvWaitKey(100)==27)break;//销毁窗⼝cvDestroyWindow("原图像");cvDestroyWindow("灰度图像");cvDestroyWindow("⼆值化图像");//释放图像cvReleaseImage(&pSrcImg);cvReleaseImage(&pGrayImg);cvReleaseImage(&pBinaryImg);return 0;}return -1;}。
16int stride = bmpData.Stride;//扫描线的宽度17int offset = stride - width;//显示宽度与扫描线宽度的间隙18IntPtr iptr = bmpData.Scan0;//获取bmpData的内存起始位置19int scanBytes = stride * height;//用stride宽度,表示这是内存区域的大小2021////下面把原始的显示大小字节数组转换为内存中实际存放的字节数组22int posScan = 0, posReal = 0;//分别设置两个位置指针,指向源数组和目标数组23byte[] pixelValues = new byte[scanBytes];//为目标数组分配内存2425for (int x = 0; x < height; x )26{27////下面的循环节是模拟行扫描28for (int y = 0; y < width; y )29{30pixelValues[posScan ] =rawValues[posReal ];31}32posScan = offset;//行扫描结束,要将目标位置指针移过那段“间隙”33}3435////用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中36System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr,scanBytes); 37bmp.UnlockBits(bmpData);//解锁内存区域3839////下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度40ColorPalette tempPalette;41using (Bitmap tempBmp = new Bitmap(1, 1,PixelFormat.Format8bppIndexed)) 42{43tempPalette = tempBmp.Palette;44}45for (int i = 0; i < 256; i )4647Color.FromArgb(i, i, i);484950515253{tempPalette.Entries[i] =}bmp.Palette = tempPalette;////算法到此结束,返回结果return bmp;54}。
opencv转换灰度算法一、什么是灰度图像灰度图像是指将彩色图像转化为黑白图像的一种表示方式。
在灰度图像中,每个像素的取值范围是0到255,表示了像素的亮度。
二、为什么需要将图像转换为灰度1.简化图像处理:在某些情况下,我们只关注图像的亮度信息,而不关心颜色。
将图像转换为灰度可以简化图像处理的复杂度。
2.提高计算效率:灰度图像只有一个通道,而彩色图像有三个通道。
处理灰度图像比处理彩色图像更快。
3.减少存储空间:灰度图像只需要一个字节来表示每个像素,而彩色图像需要三个字节。
转换为灰度可以减少存储空间的占用。
三、常用的灰度转换算法1. 算法1:平均值法平均值法是将彩色图像中的每个像素的RGB值取平均,然后赋值给灰度图像的像素值。
2. 算法2:加权平均值法加权平均值法是将彩色图像中的每个像素的RGB值按照一定的权重进行加权平均,然后赋值给灰度图像的像素值。
常用的权重分配方式是根据人眼对不同颜色的敏感度来确定。
3. 算法3:最大值法最大值法是将彩色图像中的每个像素的RGB值中的最大值赋值给灰度图像的像素值。
4. 算法4:最小值法最小值法是将彩色图像中的每个像素的RGB值中的最小值赋值给灰度图像的像素值。
四、opencv中的灰度转换函数在opencv中,提供了一个函数cv2.cvtColor()用于将彩色图像转换为灰度图像。
这个函数接受两个参数:原始图像和转换的方式。
使用平均值法将彩色图像转换为灰度图像的代码示例:import cv2image = cv2.imread('color_image.jpg')gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)五、灰度图像的应用灰度图像在图像处理中有广泛的应用: 1. 图像增强:通过调整灰度图像的像素值,可以改善图像的对比度和亮度。
2. 图像分割:通过分析灰度图像的像素值,可以将图像分割成不同的区域。
BITMAPINFO * pBmpInfo;BYTE * pBmpData;BITMAPFILEHEADER bmpHeader;BITMAPINFOHEADER bmpInfo;CFile bmpFile;CString strFileName;CString strFilter = "位图文件(*.bmp)|*.bmp|所有文件(*.*)|*.*|";CFileDialog dlg(TRUE,NULL,NULL,NULL,strFilter,this);if (!dlg.DoModal() == IDOK) return;strFileName = dlg.GetPathName();/// 通过读取位图文件显示位图if(!bmpFile.Open(strFileName,CFile::modeRead|CFile::typeBinary)) return;if (bmpFile.Read(&bmpHeader,sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER)) {AfxMessageBox("read bmp header failed!");return;}if (bmpHeader.bfType != 0x4d42){AfxMessageBox("invalid file type!");return;}if (bmpFile.Read(&bmpInfo,sizeof(BITMAPINFOHEADER)) != sizeof(BITMAPINFOHEADER)) {AfxMessageBox("read bmp infor header failed!");return;}if (bmpInfo.biBitCount != 24){AfxMessageBox("File is not 24 bit.Application doesn't support this kind of file!");return;}pBmpInfo = (BITMAPINFO *)new char[sizeof(BITMAPINFOHEADER)];if (!pBmpInfo){AfxMessageBox("memory error!");return;}memcpy(pBmpInfo,&bmpInfo,sizeof(BITMAPINFOHEADER));DWORD dataBytes = bmpHeader.bfSize - bmpHeader.bfOffBits;pBmpData = (BYTE*)new char[dataBytes];if (!pBmpData){AfxMessageBox("memory error!");delete pBmpData;return;}if (bmpFile.Read(pBmpData,dataBytes) != dataBytes){AfxMessageBox("Read bmp data failed!");delete pBmpInfo;delete pBmpData;return;}bmpFile.Close();CClientDC *pDC = new CClientDC(this);pDC->SetStretchBltMode(COLORONCOLOR);StretchDIBits(pDC->GetSafeHdc(),0,0,bmpInfo.biWidth,bmpInfo.biHeight,0,0,bmpInfo.biWidth,bmpInfo.biHeight,pBmpData,p BmpInfo,DIB_RGB_COLORS,SRCCOPY);。
VC编程实现灰度图像与彩色图像的相互转换【完整版】(文档可以直接使用,也可根据实际需要修订后使用,可编辑放心下载)VC编程实现灰度图像与彩色图像的相互转换PhotoShop的图像处理功能很强,其中有一个功能是将灰度图像转换为彩色图像,数字图像处理中,也经常要遇到灰度图像与彩色图像相互转换的问题,如何自己解决这个问题,值得大家探讨,现将我解决这类问题的方法陈述如下:工程应用中经常要遇到需要把彩色图像到灰度图像的变换的问题,采集卡过来的图像为彩色图像,为加快处理速度,要把彩色图像转换为黑白图象,这个问题比拟好解决,一般情况下彩色图像每个像素用三个字节表示,每个字节对应着R、G、B分量的亮度〔红、绿、蓝〕,转换后的黑白图像的一个像素用一个字节表示该点的灰度值,它的值在0~255之间,数值越大,该点越白,既越亮,越小那么越黑。
转换公式为Gray(i,j)=0.11*R(i,j)+0.59*G(i,j)+0.3*B(i,j),其中Gray(i,j)为转换后的黑白图像在〔i,j〕点处的灰度值,我们可以观察该式,其中绿色所占的比重最大,所以转换时可以直接使用G值作为转换后的灰度。
至于灰度图像转换为彩色图像,技术上称为灰度图像的伪彩色处理,这是一种视觉效果明显而技术又不是很复杂的图像增强技术。
灰度图像中,如果相邻像素点的灰度相差不大,但包含了丰富的信息的话,人眼那么无法从图像中提取相应的信息,因为人眼分辨灰度的能力很差,一般只有几十个数量级,但是人眼对彩色信号的分辨率却很强,这样将黑白图像转换为彩色图像人眼可以提取更多的信息量。
在转换过程中,经常采用的技术是灰度级-彩色变换,意思就是对黑白图像上的每一个像素点,取得该点的灰度值并送入三个通道经过实施不同的变换,产生相应的R、G、B的亮度值,即所求彩色图像对应像素点的彩色值,具体变换公式很多,我采用的是最常用的一种,变换曲线图如下:上图中,三个图分别代表了三个变换通道,R、G、B指的是变换后对应点的R、G、B分量值,L指的是各个分量的最大值为255,G〔x,y〕为相应点的灰度值。
24位真彩色转换为8位灰度图片(完整代码)分类:C#2011-03-04 09:29 4343人阅读评论(5) 收藏举报nullfloatgdi+byte图像处理image图像的灰度与二值化/maozefa/archive/2011/12/09/2281656.html图像的灰度化与二值化是图像处理中最常见的处理方法,也是很多图像处理方法的基础,如图像灰度统计、图像识别等。
图像的灰度化与二值化方法较多,处理过程也比较简单。
但切不可因其简单而忽视效率。
如常用的图像灰度计算公式:gray = red * 0.299 + green * 0.587 + blue * 0.114,如果在程序代码中直接套用了这个公式,因浮点数的缘故导致代码执行效率较低,如改为定点整数运算,可使执行效率大大提高。
下面是图像的灰度与二值化代码:// 定义ARGB像素结构typedef union{ARGB Color;struct{BYTE Blue;BYTE Green;BYTE Red;BYTE Alpha;};}ARGBQuad, *PARGBQuad;//---------------------------------------------------------------------------// 图像数据data灰度化VOID Gray(BitmapData *data){PARGBQuad p = (PARGBQuad)data->Scan0;INT offset = data->Stride - data->Width * sizeof(ARGBQuad);for (UINT y = 0; y < data->Height; y ++, (BYTE*)p += offset){for (UINT x = 0; x < data->Width; x ++, p ++)p->Blue = p->Green = p->Red =(UINT)(p->Blue * 29 + p->Green * 150 + p->Red * 77 + 128) >> 8;}}//---------------------------------------------------------------------------// 图像数据data灰度同时二值化,threshold阀值VOID GrayAnd2Values(BitmapData *data, BYTE threshold){PARGBQuad p = (PARGBQuad)data->Scan0;INT offset = data->Stride - data->Width * sizeof(ARGBQuad);for (UINT y = 0; y < data->Height; y ++, (BYTE*)p += offset){for (UINT x = 0; x < data->Width; x ++, p ++){if (((p->Blue * 29 + p->Green * 150 + p->Red * 77 + 128) >> 8) < threshold) p->Color &= 0xff000000;elsep->Color |= 0x00ffffff;}}}//---------------------------------------------------------------------------因本文使用的是32位图像数据,所以图像的二值化没有采用通常的赋值操作p->Blue = p->Green = p->Red = 0(或者255),而是采用了位运算。
下面是使用BCB2007和GDI+图像数据实现图像灰度和二值化的例子代码:// 锁定GDI+位位图扫描线到dataFORCEINLINEVOID LockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data){Gdiplus::Rect r(0, 0, bmp->GetWidth(), bmp->GetHeight());bmp->LockBits(&r, ImageLockModeRead | ImageLockModeWrite, PixelFormat32bppARGB, data);}//---------------------------------------------------------------------------// GDI+位图扫描线解锁FORCEINLINEVOID UnlockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data){bmp->UnlockBits(data);}//---------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender){Gdiplus::Bitmap *bmp = new Gdiplus::Bitmap(L"d:\\source1.jpg");Gdiplus::Graphics *g = new Gdiplus::Graphics(Canvas->Handle);g->DrawImage(bmp, 0, 0);BitmapData data;LockBitmap(bmp, &data);// Gray(&data);GrayAnd2Values(&data, 128);UnlockBitmap(bmp, &data);g->DrawImage(bmp, data.Width, 0);delete g;delete bmp;}//---------------------------------------------------------------------------24位真彩色转换为8位灰度图片(完整代码)//Code By xets007//转载请注明出处#include <windows.h>BOOL BMP24to8(char *szSourceFile,char *szTargetFile);int main(int argc,char* argv[]){//调用这个函数直接把24位真彩色灰度化BOOL stat=BMP24to8("c://source.bmp","c://target.bmp");return 0;}BOOL BMP24to8(char *szSourceFile,char *szTargetFile){HANDLE hSourceFile=INVALID_HANDLE_VALUE,hTargetFile=INVALID_HANDLE_VALUE;DWORD dwSourceSize=0,dwTargetSize=0;PBYTE pSource=NULL,pTarget=NULL;hSourceFile=CreateFile(szSourceFile,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if(hSourceFile==INVALID_HANDLE_VALUE)return FALSE;dwSourceSize=GetFileSize(hSourceFile,NULL);pSource=(PBYTE)VirtualAlloc(NULL,dwSourceSize,MEM_COMMIT,PAGE_READWRITE);//分配空间失败或者文件太小(BMP文件不可能小于54个字节)if(pSource==NULL||dwSourceSize<=54){CloseHandle(hSourceFile);return FALSE;}DWORD dwTemp=0;ReadFile(hSourceFile,pSource,dwSourceSize,&dwTemp,NULL);BITMAPFILEHEADER *pSourceFileHeader=(BITMAPFILEHEADER*)pSource; BITMAPINFOHEADER*pSourceInfoHeader=(BITMAPINFOHEADER*)(pSource+sizeof(BITMAPFILEHEADER));//不是BMP文件或者不是24位真彩色if(pSourceFileHeader->bfType!=0x4d42||pSourceInfoHeader->biBitCount!=24){CloseHandle(hSourceFile);VirtualFree(pSource,NULL,MEM_RELEASE);return FALSE;}CloseHandle(hSourceFile);LONG nWidth=pSourceInfoHeader->biWidth;LONG nHeight=pSourceInfoHeader->biHeight;LONG nSourceWidth=nWidth*3;if(nSourceWidth%4) nSourceWidth=(nSourceWidth/4+1)*4;LONG nTargetWidth=nWidth;if(nTargetWidth%4) nTargetWidth=(nTargetWidth/4+1)*4; dwTargetSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256 +nHeight*nTargetWidth;pTarget=(PBYTE)VirtualAlloc(NULL,dwTargetSize,MEM_COMMIT,PAGE_READWRITE);memset(pTarget,0,dwTargetSize);if(pTarget==NULL){VirtualFree(pTarget,NULL,MEM_RELEASE);return FALSE;}BITMAPFILEHEADER *pTargetFileHeader=(BITMAPFILEHEADER *)pTarget; BITMAPINFOHEADER *pTargetInfoHeader =(BITMAPINFOHEADER *)(pTarget+sizeof(BITMAPFILEHEADER));pTargetFileHeader->bfType=pSourceFileHeader->bfType;pTargetFileHeader->bfSize=dwTargetSize;pTargetFileHeader->bfReserved1=0;pTargetFileHeader->bfReserved2=0;pTargetFileHeader->bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256;pTargetInfoHeader->biBitCount=8;pTargetInfoHeader->biClrImportant=0;pTargetInfoHeader->biClrUsed=256;pTargetInfoHeader->biCompression=BI_RGB;pTargetInfoHeader->biHeight=pSourceInfoHeader->biHeight;pTargetInfoHeader->biPlanes=1;pTargetInfoHeader->biSize=sizeof(BITMAPINFOHEADER);pTargetInfoHeader->biSizeImage=nHeight*nTargetWidth;pTargetInfoHeader->biWidth=pSourceInfoHeader->biWidth;pTargetInfoHeader->biXPelsPerMeter=pSourceInfoHeader->biXPelsPerMeter; pTargetInfoHeader->biYPelsPerMeter=pSourceInfoHeader->biYPelsPerMeter; RGBQUAD *pRgb;for(int i=0;i<256;i++)//初始化8位灰度图的调色板信息{pRgb = (RGBQUAD*)(pTarget+sizeof(BITMAPFILEHEADER)+ sizeof(BITMAPINFOHEADER)+i*sizeof(RGBQUAD));pRgb->rgbBlue=i;pRgb->rgbGreen=i;pRgb->rgbRed=i;pRgb->rgbReserved=0;}for (int m=0;m<nHeight;m++)//转化真彩色图为灰度图{for(int n=0;n<nWidth;n++){pTarget[pTargetFileHeader->bfOffBits+m*nTargetWidth+n] =pSource[pSourceFileHeader->bfOffBits+m*nSourceWidth+n*3]*0.114+pSource[pSourceFileHeader->bfOffBits+m*nSourceWidth+n*3+1]*0.587+pSource[pSourceFileHeader->bfOffBits+m*nSourceWidth+n*3+2]*0.299; }}hTargetFile = CreateFile(szTargetFile,GENERIC_WRITE,FILE_SHARE_WRITE, NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);BOOL stat=WriteFile(hTargetFile,pTarget,dwTargetSize,&dwTemp,NULL); CloseHandle(hTargetFile);VirtualFree(pSource,NULL,MEM_RELEASE);VirtualFree(pTarget,NULL,MEM_RELEASE);return stat;}转化效果如下图在GDI+中将24位真彩色图转换为灰度图(原理、C#调用指针)在图像处理中,我们经常需要将真彩色图像转换为黑白图像。