C語(yǔ)言實(shí)現(xiàn)直方圖均衡化
直方圖均衡化部分是用c語(yǔ)言寫的,最后用opencv顯示原圖像,處理后圖像以及原圖和處理后圖的灰度直方圖。
雖然做出來(lái)了,均衡化效果還可以,但不知道為什么處理后圖像中有三條白線,真心搞不懂,有看出來(lái)問題的大神麻煩留言告訴我,謝謝。
(終于知道哪出問題了,原來(lái)是每行字節(jié)數(shù)求錯(cuò)了,改為L(zhǎng)ineByte=(width*8/8+3)/4*4;即可。)
下面是代碼:
#include "stdafx.h" #include<stdio.h> #include<windows.h> #include<opencv2\highgui\highgui.hpp> #include<opencv2\core\core.hpp> #include<cv.h> int main(void) { int width;//圖像寬度 int height;//圖像高度 RGBQUAD *pColorTable; unsigned char *pBmpBuf,*pBmpBuf1; BITMAPFILEHEADER bfhead; BITMAPINFOHEADER bihead; FILE *fp1=fopen("e:\\picture\\dog.bmp","rb"); if(fp1==0) return 0; fread(&bfhead,14,1,fp1); fread(&bihead,40,1,fp1); width=bihead.biWidth; height=bihead.biHeight; pColorTable=new RGBQUAD[256]; fread(pColorTable,4,256,fp1); int LineByte=0; LineByte=(width*1/4+1)*4; <span style="white-space:pre"> </span>//LineByte=(width*8/8+3)/4*4; pBmpBuf = new unsigned char[LineByte*height]; fread(pBmpBuf,LineByte*height,1,fp1); fclose(fp1); pBmpBuf1=new unsigned char[LineByte*height]; //用于存儲(chǔ)均值化后的圖像數(shù)據(jù) //統(tǒng)計(jì)每個(gè)灰度級(jí)像素點(diǎn)的個(gè)數(shù) int N[256]={0}; for(int i=0;i<height;i++) for(int j=0;j<width;j++) { unsigned char *pb1,*pb2; pb1=pBmpBuf+i*LineByte+j; N[*pb1]++; pb2=pBmpBuf1+i*LineByte+j; *pb2=*pb1; } /*for(int i=0;i<256;i++ ) printf("%d ",N[i]);*/ //統(tǒng)計(jì)最小與最大灰度值 int minGrayValue=255; int maxGrayValue=0; for(int i=0;i<height;i++) for(int j=0;j<width;j++) { unsigned char *pb; pb=pBmpBuf+i*LineByte+j; if(*pb>maxGrayValue) maxGrayValue=*pb; else if(*pb<minGrayValue) minGrayValue=*pb; } printf("%d ,%d\n",minGrayValue,maxGrayValue);//輸出最大與最小灰度值 int x=maxGrayValue-minGrayValue+1; float *p; p=new float[x]; for(int i=0;i<x;i++) { *(p+i)=(float)N[i]/(float)(width*height); //*(p+i)中存放的是灰度級(jí)為i的像素在整幅圖像中出現(xiàn) //的概率(即*(p+i)i=0,1,2,3...中存放的就是這幅圖像歸一化后的直方圖) } float *c; c=new float[x]; //定義c,用來(lái)存放累積的歸一化直方圖 for(int i=0;i<x;i++) //對(duì)c進(jìn)行初始化 { *(c+i)=0; } for(int i=0;i<x;i++) { for(int j=0;j<=i;j++) { *(c+i)+=*(p+j); } } for(int i=0;i<height;i++) for(int j=0;j<width;j++) { unsigned char *pb; pb=pBmpBuf1+i*LineByte+j; *pb=*(c+*pb)*(maxGrayValue-minGrayValue)+minGrayValue; } FILE *fp2=fopen("junhenghua.bmp","wb"); fwrite(&bfhead,14,1,fp2); fwrite(&bihead,40,1,fp2); fwrite(pColorTable,4,256,fp2); fwrite(pBmpBuf1,LineByte*height,1,fp2); fclose(fp2); //顯示原圖與處理后的圖像 IplImage *src1=cvLoadImage("e:\\picture\\dog.bmp"); IplImage *src2=cvLoadImage("junhenghua.bmp"); cvNamedWindow("原圖"); cvNamedWindow("處理后圖"); cvShowImage("原圖",src1); cvShowImage("處理后圖",src2); //顯示原圖像與處理后圖像的灰度直方圖 int size=256; float range[]={0,255}; float *ranges[]={range}; CvHistogram *hist1=cvCreateHist(1,&size, CV_HIST_ARRAY,ranges,1);//創(chuàng)建一維直方圖, CvHistogram *hist2=cvCreateHist(1,&size, CV_HIST_ARRAY,ranges,1); IplImage* gray1=cvCreateImage(cvGetSize(src1),8,1); IplImage* gray2=cvCreateImage(cvGetSize(src2),8,1); cvCvtColor(src1,gray1,CV_BGR2GRAY); cvCvtColor(src2,gray2,CV_BGR2GRAY); //vCvtColor(...),是Opencv里的顏色空間轉(zhuǎn)換函數(shù),可以實(shí)現(xiàn)RGB顏色向HSV,HSI等顏色空間的轉(zhuǎn)換,也可以轉(zhuǎn)換為灰度圖像。 //參數(shù)CV_RGB2GRAY是RGB到gray, //參數(shù)CV_GRAY2RGB是gray到RGB cvCalcHist(&gray1,hist1,0,0);//統(tǒng)計(jì)圖像在[0 255]像素的均勻分布,將統(tǒng)計(jì)結(jié)果存在結(jié)構(gòu)體中 cvCalcHist(&gray2,hist2,0,0); //draw histogram----- //統(tǒng)計(jì)直方圖中的最大直方塊 float histMax1=0,histMax2=0; cvGetMinMaxHistValue(hist1,0,&histMax1,0); cvGetMinMaxHistValue(hist2,0,&histMax2,0); //創(chuàng)建一張一維直方圖的“圖”,橫坐標(biāo)為灰度級(jí),縱坐標(biāo)為像素個(gè)數(shù) IplImage *grayHist1=cvCreateImage(cvSize(256*2,64*2),8,1); IplImage *grayHist2=cvCreateImage(cvSize(256*2,64*2),8,1); cvZero(grayHist1); cvZero(grayHist2); //分別將每個(gè)直方塊的值繪制到圖中 for(int i=0;i<255;i++) { float histValue=cvQueryHistValue_1D(hist1,i); float nextValue=cvQueryHistValue_1D(hist1,i+1); //計(jì)算直方塊4個(gè)點(diǎn)的值 CvPoint pt1=cvPoint(i*2,64*2); CvPoint pt2=cvPoint((i+1)*2,64*2); CvPoint pt3=cvPoint((i+1)*2,(64-(nextValue/histMax1)*64)*2); //nextValue/histMax是將i級(jí)像素點(diǎn)個(gè)數(shù)歸一到0~1,在*64是使其高對(duì)在0~64之間 //由于opencv圖像是以左上角為坐標(biāo)原點(diǎn),向右為x軸,向下時(shí)y軸,而顯示的直方圖是向上增長(zhǎng)的,所以用64減,將其倒過(guò)來(lái)顯示 CvPoint pt4=cvPoint(i*2, (64-(histValue/histMax1)*64)*2); int ptNum=5; CvPoint pt[5]; pt[0]=pt1; pt[1]=pt2; pt[2]=pt3; pt[3]=pt4; pt[4]=pt1; cvFillConvexPoly(grayHist1,pt,ptNum,cvScalar(255)); //填充直方塊 } for(int i=0;i<255;i++) { float histValue=cvQueryHistValue_1D(hist2,i); float nextValue=cvQueryHistValue_1D(hist2,i+1); //計(jì)算直方塊4個(gè)點(diǎn)的值 CvPoint pt1=cvPoint(i*2,64*2); CvPoint pt2=cvPoint((i+1)*2,64*2); CvPoint pt3=cvPoint((i+1)*2,(64-(nextValue/histMax2)*64)*2); //nextValue/histMax是將i級(jí)像素點(diǎn)個(gè)數(shù)歸一到0~1,在*64是使其高對(duì)在0~64之間 //由于opencv圖像是以左上角為坐標(biāo)原點(diǎn),向右為x軸,向下時(shí)y軸,而顯示的直方圖是向上增長(zhǎng)的,所以用64減,將其倒過(guò)來(lái)顯示 CvPoint pt4=cvPoint(i*2, (64-(histValue/histMax2)*64)*2); int ptNum=5; CvPoint pt[5]; pt[0]=pt1; pt[1]=pt2; pt[2]=pt3; pt[3]=pt4; pt[4]=pt1; cvFillConvexPoly(grayHist2,pt,ptNum,cvScalar(255)); //填充直方塊 } cvNamedWindow("grayHistogram1"); cvNamedWindow("grayHistogram2"); cvShowImage("grayHistogram1",grayHist1); cvShowImage("grayHistogram2",grayHist2); cvWaitKey(0); system("pause"); return 0; }
原圖:
處理后圖:
原圖直方圖:
均衡化后直方圖:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)學(xué)生籍貫信息記錄簿
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生籍貫信息記錄簿,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06C++ 設(shè)置控制臺(tái)(命令行)窗口 光標(biāo)位置,及前背景顏色
這篇文章主要介紹了C++ 設(shè)置控制臺(tái)(命令行)窗口 光標(biāo)位置,及前背景顏色,需要的朋友可以參考下2019-04-04C++實(shí)現(xiàn)將輸入復(fù)制到輸出的方法
這篇文章主要介紹了C++實(shí)現(xiàn)將輸入復(fù)制到輸出的方法,實(shí)例分析了C++字符串轉(zhuǎn)換及輸入輸出操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07C++數(shù)組模擬之單鏈表與雙鏈表和棧和隊(duì)列的實(shí)現(xiàn)過(guò)程
這篇文章主要介紹了C++數(shù)組模擬之單鏈表與雙鏈表和棧和隊(duì)列的實(shí)現(xiàn)過(guò)程,了解內(nèi)部原理是為了幫助我們做擴(kuò)展,同時(shí)也是驗(yàn)證了一個(gè)人的學(xué)習(xí)能力,如果你想讓自己的職業(yè)道路更上一層樓,這些底層的東西你是必須要會(huì)的,跟隨下文來(lái)具體了解吧2023-02-02