C語(yǔ)言實(shí)現(xiàn)二值圖像模擬灰值圖像顯示效果
本文實(shí)例為大家分享了C語(yǔ)言實(shí)現(xiàn)二值圖像模擬灰值圖像顯示效果的具體代碼,供大家參考,具體內(nèi)容如下
圖案法
圖案法(patterning)是指灰度可以用一定比例的黑白點(diǎn)組成的區(qū)域表示,從而達(dá)到整體圖象的灰度感。黑白點(diǎn)的位置選擇稱(chēng)為圖案化。
下面介紹的一種設(shè)計(jì)標(biāo)準(zhǔn)圖案的算法,是由Limb在1969年提出的。
先以一個(gè)2×2的矩陣開(kāi)始:

通過(guò)遞歸關(guān)系有:

其中Mn和Un均為2n×2n的方陣,Un的所有元素都是1。
根據(jù)這個(gè)算法M2如下,為16級(jí)灰度的標(biāo)準(zhǔn)圖案:

M3(8×8陣)比較特殊,稱(chēng)為Bayer抖動(dòng)表。M4是一個(gè)16×16的矩陣。
M3 表模擬灰值圖像顯示效果:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma pack(1) //全緊湊模式
typedef struct {
unsigned char bfType[2];
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
}bitmapFileHeader;
typedef struct {
unsigned long biSize;
unsigned long biWidth;
unsigned long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPixPerMeter;
long biYPixPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
}bitmapInfoHeader;
typedef struct{
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
}rgbQUAD;
typedef struct{
bitmapFileHeader bfHeader;
bitmapInfoHeader biHeader;
rgbQUAD palette[256];
unsigned char *imgData;
}bmp;
int main(){
FILE *fp;
if((fp=fopen("d:\Temp\\test_gray.bmp","rb"))==NULL){
perror("can not open file!");
return -1;
}
//讀入彩色bmp圖像文件頭,信息頭和圖像數(shù)據(jù)
bitmapFileHeader bfHeader;
fread(&bfHeader,14,1,fp);
bitmapInfoHeader biHeader;
fread(&biHeader,40,1,fp);
int imSize=biHeader.biSizeImage;
int width=biHeader.biWidth;
int height=biHeader.biHeight;
int bitCount=biHeader.biBitCount;
int lineBytes=(width*bitCount+31)/32*4;
fseek(fp,bfHeader.bfOffBits,SEEK_SET);
unsigned char*imageData=(unsigned char*)malloc(imSize*sizeof(unsigned char));
fread(imageData,imSize*sizeof(unsigned char),1,fp);
fclose(fp);
bmp b;
memcpy(&(b.bfHeader),&bfHeader,sizeof(bfHeader));
memcpy(&(b.biHeader),&biHeader,sizeof(biHeader));
b.imgData=(unsigned char*)malloc(sizeof(unsigned char)*imSize);
memset(b.imgData,0,sizeof(unsigned char)*imSize);
for(int i=0;i<256;i++){
b.palette[i].rgbBlue=i;
b.palette[i].rgbGreen=i;
b.palette[i].rgbRed=i;
}
int i,j,temp;
unsigned char bayer[8][8]={
0,32,8,40,2,34,10,42,
48,16,56,24,50,18,58,26,
12,44,4,36,14,46,6,38,
60,28,52,20,62,30,54,22,
3,35,11,43,1,33,9,41,
51,19,59,27,49,17,57,25,
15,47,7,39,13,45,5,37,
63,31,55,23,61,29,53,21
};
for(i=0;i<height;i++){
for(j=0;j<width;j++){
temp=imageData[lineBytes*i+j];
if((temp>>2)>bayer[i&7][j&7])
b.imgData[lineBytes*i+j]=255;
else
b.imgData[lineBytes*i+j]=0;
}
}
char savePath[]="D:\Temp\\save_test.bmp";
FILE *f_save=fopen(savePath,"wb");
if(f_save==NULL){
perror("can not open file!");
return -2;
}
fwrite(&b.bfHeader,sizeof(bitmapFileHeader),1,f_save);
fwrite(&b.biHeader,sizeof(bitmapInfoHeader),1,f_save);
fwrite(&b.palette,1024,1,f_save);
fwrite(b.imgData,sizeof(unsigned char)*b.biHeader.biSizeImage,1,f_save);
fclose(f_save);
free(imageData);
free(b.imgData);
getchar();
return 0;
}
代碼效果:

抖動(dòng)法
假設(shè)灰度級(jí)別的范圍從b(black)到w(white),中間值t為(b+w)/2,對(duì)應(yīng)256級(jí)灰度,b=0,w=255,t=127.5。設(shè)原圖中象素的灰度為g,誤差值為e,則新圖中對(duì)應(yīng)象素的值用如下的方法得到:
if g > t then 打白點(diǎn) e=g-w else 打黑點(diǎn) e=g-b 3/8 × e 加到右邊的象素 3/8 × e 加到上邊的象素 1/4 × e 加到右上方的象素
實(shí)現(xiàn)代碼:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma pack(1) //全緊湊模式
typedef struct {
unsigned char bfType[2];
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
}bitmapFileHeader;
typedef struct {
unsigned long biSize;
unsigned long biWidth;
unsigned long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPixPerMeter;
long biYPixPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
}bitmapInfoHeader;
typedef struct{
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
}rgbQUAD;
typedef struct{
bitmapFileHeader bfHeader;
bitmapInfoHeader biHeader;
rgbQUAD palette[256];
unsigned char *imgData;
}bmp;
int main(){
FILE *fp;
if((fp=fopen("d:\Temp\\test_gray.bmp","rb"))==NULL){
perror("can not open file!");
return -1;
}
//讀入彩色bmp圖像文件頭,信息頭和圖像數(shù)據(jù)
bitmapFileHeader bfHeader;
fread(&bfHeader,14,1,fp);
bitmapInfoHeader biHeader;
fread(&biHeader,40,1,fp);
int imSize=biHeader.biSizeImage;
int width=biHeader.biWidth;
int height=biHeader.biHeight;
int bitCount=biHeader.biBitCount;
int lineBytes=(width*bitCount+31)/32*4;
fseek(fp,bfHeader.bfOffBits,SEEK_SET);
unsigned char*imageData=(unsigned char*)malloc(imSize*sizeof(unsigned char));
fread(imageData,imSize*sizeof(unsigned char),1,fp);
fclose(fp);
bmp b;
memcpy(&(b.bfHeader),&bfHeader,sizeof(bfHeader));
memcpy(&(b.biHeader),&biHeader,sizeof(biHeader));
b.imgData=(unsigned char*)malloc(sizeof(unsigned char)*imSize);
memset(b.imgData,0,sizeof(unsigned char)*imSize);
for(int i=0;i<256;i++){
b.palette[i].rgbBlue=i;
b.palette[i].rgbGreen=i;
b.palette[i].rgbRed=i;
}
int i,j,temp;
double e,f;
for(i=0;i<height;i++){
for(j=0;j<width;j++){
b.imgData[lineBytes*i+j]=imageData[lineBytes*i+j]; //拷貝數(shù)據(jù)
}
}
for(i=0;i<height;i++){
for(j=0;j<width;j++){
temp=b.imgData[lineBytes*i+j];
if(temp>128){
b.imgData[lineBytes*i+j]=255;
e=(float)(temp-255);
}
else{
b.imgData[lineBytes*i+j]=0;
e=(float)temp;
}
if(j<width-1){
f=b.imgData[lineBytes*i+j+1];
f+=3.0/8.0*e;
b.imgData[lineBytes*i+j+1]=(unsigned char)f; //向右傳播
}
if(i<height-1){
f=b.imgData[lineBytes*(i+1)+j];
f+=3.0/8.0*e;
b.imgData[lineBytes*(i+1)+j]=(unsigned char)f; //向上傳播
f=b.imgData[lineBytes*(i+1)+j+1];
f+=1.0/4.0*e;
b.imgData[lineBytes*(i+1)+j+1]=(unsigned char)f; //向右上傳播
}
}
}
char savePath[]="D:\Temp\\save_test.bmp";
FILE *f_save=fopen(savePath,"wb");
if(f_save==NULL){
perror("can not open file!");
return -2;
}
fwrite(&b.bfHeader,sizeof(bitmapFileHeader),1,f_save);
fwrite(&b.biHeader,sizeof(bitmapInfoHeader),1,f_save);
fwrite(&b.palette,1024,1,f_save);
fwrite(b.imgData,sizeof(unsigned char)*b.biHeader.biSizeImage,1,f_save);
fclose(f_save);
free(imageData);
free(b.imgData);
getchar();
return 0;
}
代碼效果:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++ opencv ffmpeg圖片序列化實(shí)現(xiàn)代碼解析
這篇文章主要介紹了C++ opencv ffmpeg圖片序列化實(shí)現(xiàn)代碼解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
C語(yǔ)言 OpenCV實(shí)現(xiàn)柱面投影
在做全景拼接的時(shí)候,為了保持圖片中的空間約束與視覺(jué)的一致性,需要進(jìn)行柱面投影,否則離中心圖像距離越遠(yuǎn)的圖像拼接后變形越大。本文將具體介紹一下這如何實(shí)現(xiàn),需要的可以參考一下2021-12-12
深入探究C/C++中互斥量(鎖)的實(shí)現(xiàn)原理
? 互斥量是一種同步原語(yǔ),用于保護(hù)多個(gè)線程同時(shí)訪問(wèn)共享數(shù)據(jù),互斥量提供獨(dú)占的、非遞歸的所有權(quán)語(yǔ)義,本文將和大家一起深入探究C/C++中互斥量(鎖)的實(shí)現(xiàn)原理,感興趣的小伙伴跟著小編一起來(lái)看看吧2024-06-06
C++實(shí)現(xiàn)頁(yè)面的緩沖區(qū)管理器
這篇文章主要介紹了C++實(shí)現(xiàn)頁(yè)面的緩沖區(qū)管理器,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08
C語(yǔ)言實(shí)現(xiàn)快速排序改進(jìn)版
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)快速排序的改進(jìn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08
Qt動(dòng)態(tài)庫(kù)調(diào)用宿主進(jìn)程中的對(duì)象方法純虛函數(shù)使用
這篇文章主要為大家介紹了Qt動(dòng)態(tài)庫(kù)調(diào)用宿主進(jìn)程中的對(duì)象方法純虛函數(shù)使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
C語(yǔ)言進(jìn)階教程之字符函數(shù)和字符串函數(shù)
C語(yǔ)言中對(duì)字符和字符串的處理很是頻繁,但是C語(yǔ)言本身是沒(méi)有字符串類(lèi)型的,字符串通常放在常量字符串中或者字符數(shù)組中,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言進(jìn)階教程之字符函數(shù)和字符串函數(shù)的相關(guān)資料,需要的朋友可以參考下2022-11-11

