|
10 | 10 | namespace cv {
|
11 | 11 | namespace stMorph {
|
12 | 12 |
|
13 |
| -// Generate list of rectangles whose width and height are power of 2. |
14 |
| -// (The width and height values of returned rects are the log2 of the actual values.) |
15 |
| -std::vector<Rect> genPow2RectsToCoverKernel(InputArray _kernel) |
| 13 | +int log2(int n) |
16 | 14 | {
|
17 |
| - CV_Assert(_kernel.type() == CV_8UC1); |
18 |
| - |
19 |
| - Mat kernel = _kernel.getMat(); |
20 |
| - |
21 |
| - // generate log2 table |
22 |
| - int len = std::max(kernel.rows, kernel.cols) + 1; |
23 |
| - std::vector<int> log2(len); |
24 |
| - for (int i = 2; i < len; i++) log2[i] = log2[i >> 1] + 1; |
25 |
| - |
26 |
| - // generate sparse table for the kernel |
27 |
| - std::vector<std::vector<Mat>> st(log2[kernel.rows] + 1, std::vector<Mat>(log2[kernel.cols] + 1)); |
28 |
| - st[0][0] = kernel; |
29 |
| - int colDepthLim = log2[kernel.cols]; |
30 |
| - int rowDepthLim = log2[kernel.rows]; |
31 |
| - for (int colDepth = 1; colDepth <= colDepthLim; colDepth++) |
| 15 | + int ans = -1; |
| 16 | + while (n > 0) |
32 | 17 | {
|
33 |
| - int colStep = 1 << (colDepth - 1); |
34 |
| - int colLim = kernel.cols - (1 << colDepth) + 1; |
35 |
| - |
36 |
| - Rect rect1(0, 0, colLim, kernel.rows); |
37 |
| - Rect rect2(colStep, 0, colLim, kernel.rows); |
38 |
| - Mat src1 = st[0][colDepth - 1](rect1); |
39 |
| - Mat src2 = st[0][colDepth - 1](rect2); |
40 |
| - st[0][colDepth].create(kernel.size(), kernel.type()); |
41 |
| - Mat next = st[0][colDepth](rect1); |
42 |
| - cv::bitwise_and(src1, src2, next); |
43 |
| - if (countNonZero(next) == 0) |
44 |
| - { |
45 |
| - colDepthLim = colDepth; |
46 |
| - break; |
47 |
| - } |
| 18 | + n /= 2; |
| 19 | + ans++; |
48 | 20 | }
|
49 |
| - for (int rowDepth = 1; rowDepth <= rowDepthLim; rowDepth++) |
50 |
| - { |
51 |
| - int nonZero = 0; |
| 21 | + return ans; |
| 22 | +} |
52 | 23 |
|
53 |
| - int rowStep = 1 << (rowDepth - 1); |
54 |
| - int rowLim = kernel.rows - (1 << rowDepth) + 1; |
55 |
| - for (int colDepth = 0; colDepth <= colDepthLim; colDepth++) |
56 |
| - { |
57 |
| - int colStep = 0; |
58 |
| - int colLim = kernel.cols - (1 << colDepth) + 1; |
59 |
| - |
60 |
| - Rect rect1(0, 0, colLim, rowLim); |
61 |
| - Rect rect2(colStep, rowStep, colLim, rowLim); |
62 |
| - Mat src1 = st[rowDepth - 1][colDepth](rect1); |
63 |
| - Mat src2 = st[rowDepth - 1][colDepth](rect2); |
64 |
| - st[rowDepth][colDepth].create(kernel.size(), kernel.type()); |
65 |
| - Mat next = st[rowDepth][colDepth](rect1); |
66 |
| - cv::bitwise_and(src1, src2, next); |
67 |
| - |
68 |
| - if (colDepth == 0) |
69 |
| - { |
70 |
| - nonZero = countNonZero(next); |
71 |
| - } |
72 |
| - } |
73 |
| - if (nonZero == 0) |
| 24 | +void findSeeds(const Mat& stNode, std::vector<Rect>& const p2Rects, int rowDepth, int colDepth) |
| 25 | +{ |
| 26 | + int rowOfst = 1 << rowDepth; |
| 27 | + int colOfst = 1 << colDepth; |
| 28 | + for (int row = 0; row < stNode.rows; row++) |
| 29 | + { |
| 30 | + for (int col = 0; col < stNode.cols; col++) |
74 | 31 | {
|
75 |
| - rowDepthLim = rowDepth; |
76 |
| - break; |
| 32 | + // select white cells |
| 33 | + if (stNode.at<uchar>(row, col) == 0) continue; |
| 34 | + |
| 35 | + // select corner cells |
| 36 | + if (col > 0 && stNode.at<uchar>(row, col - 1) == 1 |
| 37 | + && col + 1 < stNode.cols && stNode.at<uchar>(row, col + 1) == 1) continue; |
| 38 | + if (row > 0 && stNode.at<uchar>(row - 1, col) == 1 |
| 39 | + && row + 1 < stNode.rows && stNode.at<uchar>(row + 1, col) == 1) continue; |
| 40 | + |
| 41 | + // zignore if neighboring block is white; will be alive in deeper table |
| 42 | + if (col + colOfst < stNode.cols && stNode.at<uchar>(row, col + colOfst) == 1) continue; |
| 43 | + if (col - colOfst >= 0 && stNode.at<uchar>(row, col - colOfst) == 1) continue; |
| 44 | + if (row + rowOfst < stNode.rows && stNode.at<uchar>(row + rowOfst, col) == 1) continue; |
| 45 | + if (row - rowOfst >= 0 && stNode.at<uchar>(row - rowOfst, col) == 1) continue; |
| 46 | + |
| 47 | + p2Rects.emplace_back(col, row, colDepth, rowDepth); |
77 | 48 | }
|
78 | 49 | }
|
| 50 | +} |
| 51 | + |
| 52 | +// Generate list of rectangles whose width and height are power of 2. |
| 53 | +// (The width and height values of returned rects are the log2 of the actual values.) |
| 54 | +std::vector<Rect> genPow2RectsToCoverKernel(InputArray _kernel) |
| 55 | +{ |
| 56 | + CV_Assert(_kernel.type() == CV_8UC1); |
| 57 | + |
| 58 | + Mat kernel = _kernel.getMat(); |
79 | 59 |
|
80 |
| - // find pow2 rectangles |
81 | 60 | std::vector<Rect> p2Rects;
|
82 |
| - for (int rowDepth = 0; rowDepth <= rowDepthLim; rowDepth++) |
| 61 | + Mat stCache = kernel; |
| 62 | + int rowLim = log2(kernel.rows); |
| 63 | + int colLim = log2(kernel.cols); |
| 64 | + for (int rowDepth = 0; rowDepth <= rowLim; rowDepth++) |
83 | 65 | {
|
84 |
| - int rowOfst = 1 << rowDepth; |
85 |
| - int rowSkip = rowOfst - 1; |
86 |
| - int rowLim = kernel.rows - rowSkip; |
87 |
| - int x = rowOfst * kernel.cols; |
88 |
| - for (int colDepth = 0; colDepth <= colDepthLim; colDepth++) |
| 66 | + Mat st = stCache.clone(); |
| 67 | + for (int colDepth = 0; colDepth <= colLim; colDepth++) |
89 | 68 | {
|
90 |
| - int colOfst = 1 << colDepth; |
91 |
| - int colSkip = colOfst - 1; |
92 |
| - int colLim = kernel.cols - colSkip; |
93 |
| - |
94 |
| - uchar* ptr = st[rowDepth][colDepth].ptr(); |
95 |
| - for (int row = 0; row < rowLim; row++) |
96 |
| - { |
97 |
| - for (int col = 0; col < colLim; col++, ptr++) |
98 |
| - { |
99 |
| - // ignore black cell |
100 |
| - if (ptr[0] == 0) continue; |
101 |
| - |
102 |
| - // ignore if both sides are white by each axis |
103 |
| - if (col > 0 && ptr[-1] == 1 |
104 |
| - && col < colLim && ptr[1] == 1) continue; |
105 |
| - if (row > 0 && ptr[-kernel.cols] |
106 |
| - && row < rowLim && ptr[kernel.cols] == 1) continue; |
107 |
| - |
108 |
| - // ignore if neighboring block is white; will be alive in deeper table |
109 |
| - if (col + colOfst < colLim && ptr[colOfst] == 1) continue; |
110 |
| - if (col - colOfst >= 0 && ptr[-colOfst] == 1) continue; |
111 |
| - if (row + rowOfst < rowLim && ptr[x] == 1) continue; |
112 |
| - if (row - rowOfst >= 0 && ptr[-x] == 1) continue; |
113 |
| - |
114 |
| - p2Rects.emplace_back(col, row, colDepth, rowDepth); |
115 |
| - } |
116 |
| - ptr += colSkip; |
117 |
| - } |
| 69 | + findSeeds(st, p2Rects, rowDepth, colDepth); |
| 70 | + int colStep = 1 << colDepth; |
| 71 | + if (st.cols - colStep < 0) break; |
| 72 | + Rect s1(0, 0, st.cols - colStep, st.rows); |
| 73 | + Rect s2(colStep, 0, st.cols - colStep, st.rows); |
| 74 | + cv::min(st(s1), st(s2), st); |
| 75 | + if (countNonZero(st) == 0) break; |
118 | 76 | }
|
| 77 | + int rowStep = 1 << rowDepth; |
| 78 | + if (stCache.rows - rowStep < 0) break; |
| 79 | + Rect s1(0, 0, stCache.cols, stCache.rows - rowStep); |
| 80 | + Rect s2(0, rowStep, stCache.cols, stCache.rows - rowStep); |
| 81 | + cv::min(stCache(s1), stCache(s2), stCache); |
| 82 | + if (countNonZero(stCache) == 0) break; |
119 | 83 | }
|
120 | 84 | return p2Rects;
|
121 | 85 | }
|
|
0 commit comments