回答編集履歴

2

説明の誤字を修正

2020/06/28 11:36

投稿

e-watt
e-watt

スコア84

test CHANGED
@@ -1,9 +1,17 @@
1
1
  回答が長くなってしまったので、「詰め直し」は別に回答します。
2
2
 
3
- こちらは全般的な参考に、ということで
3
+ こちらは全般的な参考に、ということで
4
+
5
+ なお、コンパイル前に先頭付近のマクロ NEIGHBOR により、4連結、8連結のどちらかを選んで実行できます。
4
6
 
5
7
  ```C
6
8
 
9
+ #define NEIGHBOR 4 /*連結数:4か8*/
10
+
11
+ ```
12
+
13
+ ```C
14
+
7
15
  /*
8
16
 
9
17
  ・マクロの使い方など、かなり行儀が悪い部分がありますがご了承ください。

1

コードを少々修正し、説明を別枠で行うことを追記

2020/06/28 11:35

投稿

e-watt
e-watt

スコア84

test CHANGED
@@ -1,8 +1,6 @@
1
- 肝心の「ルックアップテーブルの詰め直し」で「なぜ」「何を」やっているかの説明が未記入ですがとりあえずコードだけ這っておきます。
2
-
3
- 説明は追ってします。
1
+ 回答が長くなってしまったので、「詰め直し」は別に回答します。
2
+
4
-
3
+ こちらは府全般的な参考に、ということで
5
-
6
4
 
7
5
  ```C
8
6
 
@@ -10,10 +8,6 @@
10
8
 
11
9
  ・マクロの使い方など、かなり行儀が悪い部分がありますがご了承ください。
12
10
 
13
- ・変数名などかなりいじってしまいました。悪しからず
14
-
15
- ・インデントなども雑です。すみません
16
-
17
11
  */
18
12
 
19
13
  #include<stdio.h>
@@ -24,11 +18,11 @@
24
18
 
25
19
 
26
20
 
27
- #define NEIGHBOR 4 /*連結数4か8で指定*/
21
+ #define NEIGHBOR 4 /*連結数:4か8*/
28
-
29
-
30
-
22
+
23
+
24
+
31
- /* デバッ:画像っぽいものをなんとなく表示 */
25
+ /* デバッ用 */
32
26
 
33
27
  static void showIntMatrix(const char* name, const int* array, int width, int height, int line) {
34
28
 
@@ -66,11 +60,11 @@
66
60
 
67
61
 
68
62
 
69
- /*デバッグ用:配列の要素を横一列に表示*/
63
+ /*デバッグ用*/
70
64
 
71
65
  static void showIntArray(const char* caption, const char* name, const int* array, int N) {
72
66
 
73
- printf("%s:\n", caption);
67
+ printf("%s:\n%s ", caption, name);
74
68
 
75
69
  for (int i=1; i<=N; i++){
76
70
 
@@ -82,11 +76,11 @@
82
76
 
83
77
  }
84
78
 
85
- #define showDST(expr) showIntArray(expr, "dst", dst, ((w*h)+1)/2)
79
+ #define showDST(expr) showIntArray(expr, "Dst", dst, ((t)+1)/2)
86
80
 
87
81
  #define PartN (14)
88
82
 
89
- #define showPartOfDST(expr) showIntArray(expr, "dst", dst, PartN) /*全部出すと冗長なので先頭付近のみ表示*/
83
+ #define showPartOfDST(expr) showIntArray(expr, "Dst", dst, PartN) /*全部出すと冗長なので先頭付近のみ表示*/
90
84
 
91
85
 
92
86
 
@@ -128,7 +122,7 @@
128
122
 
129
123
  fscanf(fp, "%d", &m); //画像の輝度の階調
130
124
 
131
- fgets(junk,10,fp); // 改行を読み飛ばす
125
+ fgets(junk,10,fp); //改行を読み飛ばす
132
126
 
133
127
  printf("J[%s]len(%d)\n", junk, strlen(junk));
134
128
 
@@ -252,11 +246,11 @@
252
246
 
253
247
  fp = fopen("test.pgm", "rb");
254
248
 
255
- fgets(junk,10,fp); // ヘッダを読み飛ばす
249
+ fgets(junk,10,fp); //ヘッダを読み飛ばす
256
-
250
+
257
- fgets(junk,10,fp); // ヘッダを読み飛ばす
251
+ fgets(junk,10,fp); //ヘッダを読み飛ばす
258
-
252
+
259
- fgets(junk,10,fp); // ヘッダを読み飛ばす
253
+ fgets(junk,10,fp); //ヘッダを読み飛ばす
260
254
 
261
255
 
262
256
 
@@ -332,7 +326,7 @@
332
326
 
333
327
  int Label=0; //ラベル番号
334
328
 
335
- int NL = ((w*h)+1)/2; // ラベルの最大数
329
+ int NL = ((w*h)+1)/2; //ラベルの最大数
336
330
 
337
331
  int dst[NL+1];//ラベリング配列 ; Srcは書き換えないし連番だから、Dstしか用意しないぜ
338
332
 
@@ -340,11 +334,11 @@
340
334
 
341
335
  for (i=1;i<=NL;i++){
342
336
 
343
- dst[i] = i; // [1]から[((w*h)+1)/2]にその値を入れるぜ;
337
+ dst[i] = i; //[1]から[((w*h)+1)/2]にその値を入れるぜ;
344
-
338
+
345
- // ただし質問者様は要素数と末尾の処理を間違ってるっぽい
339
+ //ただし質問者様は要素数と末尾の処理を間違ってるっぽい
346
-
340
+
347
- // + 領域数の最大値は、市松模様に塗り分けられた時の ceil(W*H/2) 3x3マスだと5個まであり
341
+ //+ 領域数の最大値は、市松模様に塗り分けられた時の ceil(W*H/2) 3x3マスだと5個まであり
348
342
 
349
343
  }
350
344
 
@@ -370,7 +364,7 @@
370
364
 
371
365
 
372
366
 
373
- /* (x,y)のラベル番号を与える。画像の範囲外に対してゼロを与える */
367
+ /* (x,y)のラベル番号を与える。画像の範囲外に対してゼロを与える */
374
368
 
375
369
  #define getLabel(x,y) ((0<=(x)&&(x)<w && 0<=(y)) ? labeled_image[x][y] : 0)
376
370
 
@@ -388,13 +382,13 @@
388
382
 
389
383
  if(image[j][i]==1){ //対象画素が1
390
384
 
391
- int up_m = getLabel(j, i-1); // 上 4/8連結で共通
385
+ int up_m = getLabel(j, i-1); //上 4/8連結で共通
392
-
386
+
393
- int left = getLabel(j-1, i); // 左 4/8連結で共通
387
+ int left = getLabel(j-1, i); //左 4/8連結で共通
394
388
 
395
389
  #if NEIGHBOR == 4 //4連結
396
390
 
397
- if (up_m == 0 && left == 0) { // コメントは8連結側を参照されたし
391
+ if (up_m == 0 && left == 0) { //コメントは8連結側を参照されたし
398
392
 
399
393
  labeled_image[j][i] = ++Label;
400
394
 
@@ -410,7 +404,7 @@
410
404
 
411
405
  labeled_image[j][i] = min;
412
406
 
413
- dst[up_m] = nonzeroMin(dst[up_m], min); // 双方ゼロではないので実は普通のmin(a,b)でよい
407
+ dst[up_m] = nonzeroMin(dst[up_m], min); //双方ゼロではないので実は普通のmin(a,b)でよい
414
408
 
415
409
  dst[left] = nonzeroMin(dst[left], min);
416
410
 
@@ -420,19 +414,19 @@
420
414
 
421
415
  #elif NEIGHBOR == 8
422
416
 
423
- int up_l = getLabel(j-1, i-1); // 左上
417
+ int up_l = getLabel(j-1, i-1); //左上
424
-
418
+
425
- int up_r = getLabel(j+1, i-1); // 右上
419
+ int up_r = getLabel(j+1, i-1); //右上
426
420
 
427
421
 
428
422
 
429
- // 『』内は参照ページの記述の引用;なるべく書いてある通りに作るぜ
423
+ //『』内は参照ページの記述の引用;なるべく書いてある通りに作るぜ
430
-
424
+
431
- // 『左上、上、右上、左の画素のラベル番号を参照し、全て0(ゼロ)の場合は』
425
+ //『左上、上、右上、左の画素のラベル番号を参照し、全て0(ゼロ)の場合は』
432
426
 
433
427
  if (up_l == 0 && up_m == 0 && up_r == 0 && left == 0) {
434
428
 
435
- labeled_image[j][i] = ++Label; // 『最後に割り振った番号+1のラベル番号を割り振ります。』
429
+ labeled_image[j][i] = ++Label; //『最後に割り振った番号+1のラベル番号を割り振ります。』
436
430
 
437
431
  _TL_
438
432
 
@@ -454,11 +448,11 @@
454
448
 
455
449
  min = nonzeroMin(left, min);
456
450
 
457
- labeled_image[j][i] = min; // (0以外の)『最小の番号を割り振ります。』
451
+ labeled_image[j][i] = min; //(0以外の)『最小の番号を割り振ります。』
458
452
 
459
453
  _Tm_
460
454
 
461
- // 『用いなかったラベル番号のルックアップテーブルの番号を最小の番号に書き換えます。』
455
+ //『用いなかったラベル番号のルックアップテーブルの番号を最小の番号に書き換えます。』
462
456
 
463
457
  /* ループ内でdst[0] は未使用だ(参照しない)からチェックせずにガンガン上書きするぜ*/
464
458
 
@@ -484,7 +478,7 @@
484
478
 
485
479
  }
486
480
 
487
- showLabeledImage(); // 一行操作するごとに表示する…と、解説ページと似た感じの出力に
481
+ showLabeledImage(); //一行操作するごとに表示する…と、解説ページと似た感じの出力に
488
482
 
489
483
  }
490
484
 
@@ -500,15 +494,15 @@
500
494
 
501
495
 
502
496
 
503
- /* ルックアップテーブルの詰め替え;思いのほか面倒;もっといいやり方はありそう */
497
+ /* ルックアップテーブルの詰め替え */
504
-
505
-
506
-
498
+
499
+
500
+
507
- int conv[NL+1]; //
501
+ int conv[NL+1]; //
508
502
 
509
503
  for (i=1;i<=NL;i++){
510
504
 
511
- conv[i] = -1; // すべて「未定」にする
505
+ conv[i] = -1; //すべて「未定」にする
512
506
 
513
507
  }
514
508
 
@@ -518,56 +512,54 @@
518
512
 
519
513
 
520
514
 
521
- //再帰的結合 ;
515
+ //再帰的結合; ←これは回答者の勝手な命名で、専門用語ではない
522
-
523
- for (i=1;i<=NL;i++){
516
+
524
-
525
- for (j=1;j<=NL;j++){
517
+ for (j=1;j<=NL;j++){
526
-
518
+
527
- while (dst[j] != dst[ dst[j] ])
519
+ while (dst[j] != dst[ dst[j] ])
528
-
520
+
529
- dst[j] = dst[ dst[j] ];
521
+ dst[j] = dst[ dst[j] ];
530
-
522
+
531
- }
523
+ }
524
+
525
+
526
+
527
+ showPartOfDST("recursed");
528
+
529
+
530
+
531
+ //番号を圧縮; 説明しないとわからんと思う
532
+
533
+ int seqn = 1;
534
+
535
+ for (i=1;i<=13;i++){
536
+
537
+ int dstQ = dst[i];
538
+
539
+ printf("[%2d] dstQ=%2d conv[dstQ]=%2d...",i, dstQ, conv[dstQ]);
540
+
541
+ if (conv[ dstQ ] == -1) {
542
+
543
+ conv[ dstQ ] = seqn;
544
+
545
+ printf("conv[%2d] gets-to %2d", dstQ, seqn);
546
+
547
+ ++seqn;
548
+
549
+ }else{
550
+
551
+ printf("%19s", "");
552
+
553
+ }
554
+
555
+ printf(" dst[%2d]<<%2d, dstQ=%2\n", i, conv[dstQ], dstQ);
556
+
557
+
558
+
559
+ dst[i] = conv[dstQ];
532
560
 
533
561
  }
534
562
 
535
- showPartOfDST("recursed");
536
-
537
-
538
-
539
- // 番号を圧縮; 説明しないとわからんと思う
540
-
541
- int seqn = 1;
542
-
543
- for (i=1;i<=13;i++){
544
-
545
- int dstQ = dst[i];
546
-
547
- printf("[%2d] dstQ=%2d conv[dstQ]=%2d...",i, dstQ, conv[dstQ]);
548
-
549
- if (conv[ dstQ ] == -1) {
550
-
551
- conv[ dstQ ] = seqn;
552
-
553
- printf("conv[%2d] gets-to %2d", dstQ, seqn);
554
-
555
- ++seqn;
556
-
557
- }else{
558
-
559
- printf("%19s", "");
560
-
561
- }
562
-
563
- printf(" dst[%2d]<<%2d, dstQ=%2\n", i, conv[dstQ], dstQ);
564
-
565
-
566
-
567
- dst[i] = conv[dstQ];
568
-
569
- }
570
-
571
563
 
572
564
 
573
565
  showIntArray("Conv:", "conv", conv, PartN);
@@ -578,9 +570,7 @@
578
570
 
579
571
 
580
572
 
581
- // ルックアップテーブルに従い結果を書き換え
573
+ //ルックアップテーブルに従い結果を書き換え
582
-
583
- // 上でさんざんdst[0]に好き放題したが、ここでは参照しうるので本来の値を入れる
584
574
 
585
575
  dst[0] = 0;
586
576
 
@@ -594,13 +584,13 @@
594
584
 
595
585
  }
596
586
 
597
- // 最終結果を表示
587
+ //最終結果を表示
598
588
 
599
589
  showLabeledImage();
600
590
 
601
591
 
602
592
 
603
- printf("%d連結の連結成分の個数=%d\n", NEIGHBOR, dst[Label]); /*使われたラベルの値(最大値)の圧縮結果が領域の数*/
593
+ printf("%d連結の連結成分の個数=%d?\n", NEIGHBOR, dst[Label]); /*使われたラベルの値(最大値)の圧縮結果が領域の数…とは限らなそう*/
604
594
 
605
595
 
606
596