C語(yǔ)言實(shí)現(xiàn)BMP圖像開(kāi)運(yùn)算處理
開(kāi)運(yùn)算可以把比結(jié)構(gòu)元素小的特定圖像細(xì)節(jié)出去,同時(shí)保證不產(chǎn)生全局的幾何失真。濾掉比結(jié)構(gòu)元素小的突刺,切斷細(xì)長(zhǎng)搭接而起到分離作用。
運(yùn)算:用B開(kāi)啟A就是選出了A中某些與B相匹配的點(diǎn),這些點(diǎn)可由完全包含在A中的結(jié)構(gòu)元素B的平移得到。也就是先腐蝕后加膨脹。
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
int main(int* argc, char** argv)
{
FILE* fp = fopen("./threshold.bmp", "rb");
if (fp == 0)
return 0;
BITMAPFILEHEADER fileHead;
fread(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
BITMAPINFOHEADER infoHead;
fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);
int width = infoHead.biWidth;
int height = infoHead.biHeight;
int biCount = infoHead.biBitCount;
int lineByte = (biCount*width / 8 + 3) / 4 * 4;
RGBQUAD* pColorTable;
pColorTable = new RGBQUAD[256];
fread(pColorTable, sizeof(RGBQUAD), 256, fp);
unsigned char* pBmpBuf;
pBmpBuf = new unsigned char[lineByte*height];
fread(pBmpBuf, lineByte*height, 1, fp);
fclose(fp);
// 新圖
FILE* fop = fopen("open.bmp", "wb");
if (fop == 0)
return 0;
// 定義結(jié)構(gòu)元素
// 腐蝕操作
int t = 0, d = 0, r = 0;
for (int i = 1; i < height; ++i){
for (int j = 0; j < width - 1; ++j){
t = *(pBmpBuf + i*lineByte + j); // 當(dāng)前點(diǎn)
d = *(pBmpBuf + (i - 1)*lineByte + j); // 下面點(diǎn)
r = *(pBmpBuf + i*lineByte + j + 1); // 右邊點(diǎn)
if (t == 0 && d != 0){
*(pBmpBuf + (i - 1)*lineByte + j) = 0;//下邊的置位1
}
if (t == 0 && r != 0){
*(pBmpBuf + i*lineByte + j + 1) = 0;//右邊的置位1
j = j + 1;
}
}
}
// 膨脹操作
// 初始化
unsigned char* pBmpBuf2;
pBmpBuf2 = new unsigned char[lineByte*height];
for (int i = 0; i < height; ++i){
for (int j = 0; j < width; ++j){
*(pBmpBuf2 + i*lineByte + j) = 255;
}
}
// 腐蝕操作
for (int i = 1; i < height; ++i){
for (int j = 0; j < width - 1; ++j){
t = *(pBmpBuf + i*lineByte + j); // 當(dāng)前點(diǎn)
d = *(pBmpBuf + (i - 1)*lineByte + j); // 下面點(diǎn)
r = *(pBmpBuf + i*lineByte + j + 1); // 右邊點(diǎn)
if (t == 0 && d == 0 && r == 0){
*(pBmpBuf2 + i*lineByte + j) = 0; // 當(dāng)前點(diǎn)
}
}
}
// 結(jié)構(gòu)元素向上反轉(zhuǎn)180度,對(duì)最下面一排處理
for (int j = 0; j < width - 1; ++j){
t = *(pBmpBuf + j); // 當(dāng)前點(diǎn)
d = *(pBmpBuf + lineByte + j); // 上面點(diǎn)
r = *(pBmpBuf + j + 1); // 右邊點(diǎn)
if (t == 0 && d == 0 && r == 0){
*(pBmpBuf2 + j) = 0; // 當(dāng)前點(diǎn)
}
}
// 結(jié)構(gòu)元素向右反轉(zhuǎn),對(duì)最右邊一列處理
for (int i = 1; i < height; ++i){
t = *(pBmpBuf + i*lineByte + width - 1);
d = *(pBmpBuf + (i - 1)*lineByte + width - 1);
r = *(pBmpBuf + i*lineByte + width - 2);
if (t == 0 && d == 0 && r == 0){
*(pBmpBuf2 + i*lineByte + width - 1) = 0; // 當(dāng)前點(diǎn)
}
}
fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fop);
fwrite(&infoHead, sizeof(BITMAPINFOHEADER), 1, fop);
fwrite(pColorTable, sizeof(RGBQUAD), 255, fop);
fwrite(pBmpBuf2, lineByte*height, 1, fop);
fclose(fop);
system("pause");
return 0;
}
實(shí)驗(yàn)結(jié)果:

實(shí)驗(yàn)結(jié)果分析:效果圖和原圖差別不大。但細(xì)節(jié)如眼睛略微由區(qū)別。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言對(duì)棧的實(shí)現(xiàn)基本操作
棧只允許在一端進(jìn)行插入或刪除操作的線(xiàn)性表。首先棧是一種線(xiàn)性表,但是限定這種線(xiàn)性表只能在某一端進(jìn)行插入和刪除操作,這篇文章主要介紹了C語(yǔ)言對(duì)棧的實(shí)現(xiàn)基本操作.2016-10-10
C與C++動(dòng)態(tài)分配二維數(shù)組的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇C與C++動(dòng)態(tài)分配二維數(shù)組的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12
c語(yǔ)言中缺省參數(shù)的類(lèi)型總結(jié)
在本篇文章里小編給大家整理了一篇關(guān)于c語(yǔ)言中缺省參數(shù)的類(lèi)型總結(jié)內(nèi)容,有興趣的朋友們可以跟著學(xué)習(xí)參考下。2021-09-09
C++實(shí)現(xiàn)掃雷小游戲(控制臺(tái))
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05

