001: //-----------------------------------------------------------------
002: // binalize.cpp:
003: //      2値画像の画像処理
004: //                 Last Update: <2004/12/10 08:46:26 A.Murakami>
005: //-----------------------------------------------------------------
006: #include "binalize.h"
007: //-----------------------------------------------------------------
008: // 2値画像の取得[グレースケール, R/G/B の2値化]
009: //-----------------------------------------------------------------
010: LPBYTE GetBin(int bwopt,int bkgopt)
011: {
012:     LPBYTE iBin;
013:     switch(bwopt){
014:     case BW_NORMAL: iBin = GetGray();        break;
015:     case BW_COLR:   iBin = GetColor(iRED);   break;
016:     case BW_COLG:   iBin = GetColor(iGREEN); break;
017:     case BW_COLB:   iBin = GetColor(iBLUE);  break;
018:     default:        iBin = GetGray();        break;
019:     }
020:     GrayToBin(iBin,bkgopt);
021:     return iBin;
022: }
023: //-----------------------------------------------------------------
024: // n値画像の取得[グレースケール, R/G/B のn値化]
025: //-----------------------------------------------------------------
026: LPBYTE GetNCol(int col_n,int bwopt,int bkgopt)
027: {
028:     LPBYTE iNcol;
029:     switch(bwopt){
030:     case BW_NORMAL: iNcol = GetGray();        break;
031:     case BW_COLR:   iNcol = GetColor(iRED);   break;
032:     case BW_COLG:   iNcol = GetColor(iGREEN); break;
033:     case BW_COLB:   iNcol = GetColor(iBLUE);  break;
034:     default:        iNcol = GetGray();        break;
035:     }
036:     GrayToNCol(iNcol,col_n,bkgopt);
037:     return iNcol;
038: }
039: //-----------------------------------------------------------------
040: // 2値化
041: //-----------------------------------------------------------------
042: void Binalize(int bkgopt)
043: {
044:     int i,j,thr[50];
045:     BYTE gray,iH,iL;
046:     // ヒストグラムの作成[濃淡化]
047:     toGray();
048:     // [2..]値化最適しきい値の計算
049:     calc_opthmdthr(2,iWHITE+1,iSize,(int*)iGHist,thr);
050:     // 背景部の自動選択
051:     iH = iWHITE; iL = iBLACK;
052:     if(bkgopt==BW_BKG_AUTO){
053:         int cnt1=0,cnt2=0;
054:         for(i=0;i<thr[1];i++)      cnt1+=iGHist[i];
055:         for(i=thr[1];i<iWHITE;i++) cnt2+=iGHist[i];
056:         if(cnt2>cnt1){
057:             iH = iBLACK; iL = iWHITE;
058:         }
059:     }
060:     // 2値画像の作成
061:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
062:         gray=lpBMP[j*3+i*iLength];
063:         if(gray>thr[1]){
064:             FillMemory(lpBMP+j*3+i*iLength,3,iH);
065:         } else {
066:             FillMemory(lpBMP+j*3+i*iLength,3,iL);
067:         }
068:     }
069: }
070: //-----------------------------------------------------------------
071: // しきい値を指定して2値化
072: //-----------------------------------------------------------------
073: void ThrBinalize(int thr)
074: {
075:     int i,j; BYTE gray;
076:     // 濃淡化
077:     toGray();
078:     // 2値画像の作成
079:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
080:         gray=lpBMP[j*3+i*iLength];
081:         if(gray>thr){
082:             FillMemory(lpBMP+j*3+i*iLength,3,iWHITE);
083:         } else {
084:             FillMemory(lpBMP+j*3+i*iLength,3,iBLACK);
085:         }
086:     }
087: }
088: //-----------------------------------------------------------------
089: // グレースケールから2値化
090: //-----------------------------------------------------------------
091: void GrayToBin(LPBYTE inBuf,int bkgopt)
092: {
093:     BYTE r,g,b,gray;
094:     BYTE iH,iL;
095:     int i,j,hist[512],thr[50];
096:     FillMemory(hist,sizeof(int)*512,0);
097:     // ヒストグラムの作成[濃淡化]
098:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
099:         hist[inBuf[j+i*iWidth]]++;
100:     }
101:     // [2..]値化最適しきい値の計算
102:     calc_opthmdthr(2,iWHITE+1,iSize,hist,thr);
103:     // 背景部の自動選択
104:     iH = iWHITE; iL = iBLACK;
105:     if(bkgopt==BW_BKG_AUTO){
106:         int cnt1=0,cnt2=0;
107:         for(i=0;i<thr[1];i++)      cnt1+=hist[i];
108:         for(i=thr[1];i<iWHITE;i++) cnt2+=hist[i];
109:         if(cnt2>cnt1){
110:             iH = iBLACK; iL = iWHITE;
111:         }
112:     }
113:     // 2値画像の作成
114:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
115:         gray=inBuf[j+i*iWidth];
116:         if(gray>thr[1]){
117:             inBuf[j+i*iWidth] = iH;
118:         } else {
119:             inBuf[j+i*iWidth] = iL;
120:         }
121:     }
122: }
123: //-----------------------------------------------------------------
124: // n値化
125: //-----------------------------------------------------------------
126: void toNCol(int col_n,int bkgopt)
127: {
128:     BYTE r,g,b,gray,colmap[50];
129:     int i,j,ii,thr[50];
130:     // ヒストグラムの作成[濃淡化]
131:     toGray();
132:     // [n..]値化最適しきい値の計算
133:     calc_opthmdthr(col_n,iWHITE+1,iSize,(int*)iGHist,thr);
134:     // 背景部の自動選択
135:     for(i=0;i<col_n;i++){
136:         colmap[i] = i*iWHITE/(col_n-1);
137:     }
138:     if(bkgopt==BW_BKG_AUTO){
139:         int hcnt[50],hmax=0,maxi=0;
140:         FillMemory(hcnt,sizeof(int)*50,0);
141:         for(i=1;i<=col_n;i++){
142:             for(ii=thr[i-1];ii<thr[i];ii++)
143:                 hcnt[i-1]+=iGHist[ii];
144:         }
145:         for(i=0;i<col_n;i++){
146:             if(hcnt[i]>hmax){
147:                 maxi = i; hmax = hcnt[i];
148:             }
149:         }
150:         if(maxi!=0){
151:             BYTE c = colmap[0];
152:             for(i=0;i<maxi;i++) colmap[i] = colmap[i+1];
153:             colmap[maxi] = c;
154:         }
155:     }
156:     // n値画像の作成
157:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
158:         gray=lpBMP[j*3+i*iLength];
159:         for(ii=col_n-1;ii>=0;ii--){
160:             if(gray>=thr[ii]){
161:                 FillMemory(lpBMP+j*3+i*iLength,3,colmap[ii]);
162:                 break;
163:             }
164:         }
165:     }
166: }
167: //-----------------------------------------------------------------
168: // グレースケールからn値化
169: //-----------------------------------------------------------------
170: void GrayToNCol(LPBYTE inBuf,int col_n,int bkgopt=BW_BKG_NORMAL)
171: {
172:     BYTE gray,colmap[50];
173:     int i,j,ii,thr[50];
174:     // [n..]値化最適しきい値の計算
175:     calc_opthmdthr(col_n,iWHITE+1,iSize,(int*)iGHist,thr);
176:     // 背景部の自動選択
177:     for(i=0;i<col_n;i++){
178:         colmap[i] = i*iWHITE/(col_n-1);
179:     }
180:     if(bkgopt==BW_BKG_AUTO){
181:         int hcnt[50],hmax=0,maxi=0;
182:         FillMemory(hcnt,sizeof(int)*50,0);
183:         for(i=1;i<=col_n;i++){
184:             for(ii=thr[i-1];ii<thr[i];ii++)
185:                 hcnt[i-1]+=iGHist[ii];
186:         }
187:         for(i=0;i<col_n;i++){
188:             if(hcnt[i]>hmax){
189:                 maxi = i; hmax = hcnt[i];
190:             }
191:         }
192:         if(maxi!=0){
193:             BYTE c = colmap[0];
194:             for(i=0;i<maxi;i++) colmap[i] = colmap[i+1];
195:             colmap[maxi] = c;
196:         }
197:     }
198:     // n値画像の作成
199:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
200:         gray=inBuf[j+i*iWidth];
201:         for(ii=col_n-1;ii>=0;ii--){
202:             if(gray>=thr[ii]){
203:                 inBuf[j+i*iWidth] = colmap[ii];
204:                 break;
205:             }
206:         }
207:     }
208: }
209: //-----------------------------------------------------------------
210: // 2値画像の8近傍収縮/膨張処理(Erosion/Dilatation)
211: //   repetition: 処理回数
212: //-----------------------------------------------------------------
213: void bwExpand(LPBYTE inBuf,int opt,int repetition)
214: {
215:     int px_count;         // 近傍中の背景画素の数
216:     int p_x,p_y;          // 近傍の(x,y)座標
217:     BYTE iFIND,iFILL;     // 白/黒 色:2値画像
218:     LPBYTE tempBuf;       // 一時保存
219:     int i,ii,x,y,m,n;
220:     if(opt==BW_EROSION) { // 収縮
221:         iFIND = iWHITE; iFILL = iBLACK;
222:     } else {              // 膨張
223:         iFIND = iBLACK; iFILL = iWHITE;
224:     }
225:     // 複製
226:     tempBuf=(LPBYTE)GlobalAlloc(GPTR,iSize);
227:     CopyMemory(tempBuf,inBuf,iSize);
228:     for(i=0;i<repetition;i++){
229:         for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++){
230:             if(inBuf[x+y*iWidth] == iFIND){
231:                 px_count = 0;
232:                 for(ii=0;ii<8;ii++){
233:                     p_x=x+offset8[i].x; p_y=y+offset8[i].y;
234:                     if(p_x>0 && p_x<iWidth && p_y>0 && p_y<iHeight){
235:                         if(inBuf[p_x+p_y*iWidth]==iFILL)
236:                             px_count ++;
237:                     }
238:                 }
239:                 if(px_count) tempBuf[x+y*iWidth] = iFILL;
240:             }
241:         }
242:         CopyMemory(inBuf,tempBuf,iSize);
243:     }
244:     GlobalFree(tempBuf);
245: }
246: //-----------------------------------------------------------------
247: // 2値画像の細線化処理 (Hilditch の方法)
248: //-----------------------------------------------------------------
249: void bw_thinning(LPBYTE inBuf)
250: {
251:     int ia[9],ic[9],i,ix,iy,px,py,m,ir,iv,iw;
252:     int iWH=255,iBW=0,iGRAY=100; // 白/黒 色:2値画像
253:     LPBYTE tempBuf;  // 一時保存
254:     // 複製
255:     tempBuf=(LPBYTE)GlobalAlloc(GPTR,iHeight*iLength);
256:     CopyMemory(tempBuf,inBuf,iSize);
257:     // 処理開始
258:     m=iGRAY; ir=1;
259:     while(ir!=0){
260:         ir=0;
261:         for(iy=1;iy<iHeight-1;iy++) for(ix=1;ix<iWidth-1;ix++){
262:             if(tempBuf[ix+iy*iWidth]!=iWH) continue;
263:             for(i=0;i<8;i++){
264:                 px = ix+offset8[i].x;
265:                 py = iy+offset8[i].y;
266:                 ia[i] = tempBuf[px+py*iWidth];
267:             }
268:             for(i=0;i<8;i++){
269:                 if(ia[i]==m){
270:                     ia[i] = iWH; ic[i] = 0;
271:                 } else {
272:                     if(ia[i]<iWH) ia[i]=0;
273:                     ic[i] = ia[i];
274:                 }
275:             }
276:             ia[8] = ia[0]; ic[8] = ic[0];
277:             if(ia[0]+ia[2]+ia[4]+ia[6] == iWH*4) continue;
278:             for(i=0,iv=0,iw=0;i<8;i++){
279:                 if(ia[i]==iWH) iv++;
280:                 if(ic[i]==iWH) iw++;
281:             }
282:             if(iv<=1) continue;
283:             if(iw==1) continue;
284:             if(func_cconc(ia)!=1) continue;
285:             if(tempBuf[ix+(iy-1)*iWidth]==m){
286:                 ia[2] = 0;
287:                 if(func_cconc(ia)!=1) continue;
288:                 ia[2] = iWH;
289:             }
290:             if(tempBuf[(ix-1)+iy*iWidth]==m){
291:                 ia[4] = 0;
292:                 if(func_cconc(ia)!=1) continue;
293:                 ia[4] = iWH;
294:             }
295:             tempBuf[ix+iy*iWidth]=m; ir++;
296:         }
297:         m++;
298:     }
299:     for(iy=1;iy<iHeight-1;iy++) for(ix=1;ix<iWidth-1;ix++){
300:         if(tempBuf[ix+iy*iWidth]<iWH)
301:             tempBuf[ix+iy*iWidth] = iBW;
302:     }
303:     // 複製
304:     CopyMemory(inBuf,tempBuf,iSize);
305:     GlobalFree(tempBuf);
306: }
307: //-----------------------------------------------------------------
308: // 注目画素の連結度(8連結)を求める関数
309: //-----------------------------------------------------------------
310: int func_cconc(int *inb)
311: {
312:     int i,icn=0,iWH=255,iBL=0;
313:     for(i=0;i<8;i+=2)
314:         if(inb[i]==iBL && (inb[i+1]==iWH || inb[i+2]==iWH))
315:             icn++;
316:     return(icn);
317: }
inserted by FC2 system