tdnki @ ウィキ
Optimization
最終更新:
tdnki
-
view
5. 画像処理の高速化
30fps(33ms)を目指して高速化していく。
現時点で1フレームの画像処理にかかる時間は80ms。
画像処理とは別に、描画にすでに10ms消費しているので、画像処理は23ms以下を目標とする。
画像処理とは別に、描画にすでに10ms消費しているので、画像処理は23ms以下を目標とする。
5-1. ループ統合
画像の3値化と輪郭抽出で、2回に分けて全ピクセルをなめているが、
これは統合可能。
これは統合可能。
ComicFinder.cpp
int lum, fx, fy, im, ip, jm, jp; for (int i = 0; i < height; i++) { im = i-1; ip = i+1; im = im < 0 ? 0 : im; ip = ip > height-1 ? height-1 : ip; for (int j = 0; j < width; j++) { lum = p_src[i*width+j]; if (lum < threshold_black_and_gray) { lum = 0x00; } else if (lum < threshold_gray_and_white) { lum = ((i+j) % 2) == 0 ? 0x00 : 0xff; } else { lum = 0xff; } if (lum != 0x00) { jm = j-1; jp = j+1; jm = jm < 0 ? 0 : jm; jp = jp > width-1 ? width-1 : jp; fx = 0; fx += p_src[im*width+jm] * -1; fx += p_src[i *width+jm] * -2; fx += p_src[ip*width+jm] * -1; fx += p_src[im*width+jp] * 1; fx += p_src[i *width+jp] * 2; fx += p_src[ip*width+jp] * 1; fy = 0; fy += p_src[im*width+jm] * -1; fy += p_src[im*width+j ] * -2; fy += p_src[im*width+jp] * -1; fy += p_src[ip*width+jm] * 1; fy += p_src[ip*width+j ] * 2; fy += p_src[ip*width+jp] * 1; lum = abs(fx) + abs(fy); lum = lum < threshold_edge ? 0xff : 0x00; } p_dst[(i*width+j)*4+0] = p_dst[(i*width+j)*4+1] = p_dst[(i*width+j)*4+2] = lum; p_dst[(i*width+j)*4+3] = 0xff; } }
80ms → 50ms。
5-2. ラインバッファ
上下左右のピクセルを参照するSobelフィルタは、領域外を参照しないよう端点で分岐処理(jm, jp等の座標計算に三項演算を使用)しているので、
今後予定しているNEONコードを利用した並列処理に置き換えにくい。
今後予定しているNEONコードを利用した並列処理に置き換えにくい。
そのため、入力画像の1ラインに対して、両端のピクセルをコピーした
長さ(width+2)のラインバッファを3本用意する形に変更し、端点の条件分岐を消しておく。
長さ(width+2)のラインバッファを3本用意する形に変更し、端点の条件分岐を消しておく。
(NEON化しないとしても、条件分岐が消えることで高速化に繋がる可能性が高い。)
ComicFinder.cpp
// ラインバッファの初期化 unsigned char line_buf[(width+2)*3]; unsigned char *line0 = line_buf; unsigned char *line1 = line0 + width+2; unsigned char *line2 = line1 + width+2; memcpy(line1+1, p_src, width); line1[0] = line1[1]; line1[width+1] = line1[width]; memcpy(line2+1, p_src+width, width); line2[0] = line2[1]; line2[width+1] = line2[width]; memcpy(line0, line1, width+2);
// ラインバッファを参照する形に変更 fx = 0; fx += line0[j+0] * -1; fx += line1[j+0] * -2; fx += line2[j+0] * -1; fx += line0[j+2] * 1; fx += line1[j+2] * 2; fx += line2[j+2] * 1; fy = 0; fy += line0[j+0] * -1; fy += line0[j+1] * -2; fy += line0[j+2] * -1; fy += line2[j+0] * 1; fy += line2[j+1] * 2; fy += line2[j+2] * 1; lum = abs(fx) + abs(fy); lum = lum < threshold_edge ? 0xff : 0x00;
// heightのループの最後でラインバッファを更新 unsigned char *tmp = line0; line0 = line1; line1 = line2; line2 = tmp; memcpy(line2+1, p_src+(i+1 > height-1 ? height-1 : i+1)*width, width); line2[0] = line2[1]; line2[width+1] = line2[width];
50ms → 40ms。
ここまでのソース
ComicFinder.zip
添付ファイル