5 * Created by Ralf Kistner on 7/12/2009.
6 * Copyright 2008 ZXing authors All rights reserved.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
21 #include <zxing/common/EdgeDetector.h>
27 namespace EdgeDetector {
29 void findEdgePoints(std::vector<Point>& points, const BitMatrix& image, Point start, Point end, bool invert, int skip, float deviation) {
30 float xdist = end.x - start.x;
31 float ydist = end.y - start.y;
32 float length = sqrt(xdist * xdist + ydist * ydist);
37 if (abs(xdist) > abs(ydist)) {
42 var = int(abs(deviation * length / xdist));
44 float dy = ydist / xdist * skip;
45 bool left = (skip < 0) ^ invert;
48 int steps = int(xdist / skip);
49 for (int i = 0; i < steps; i++) {
51 if (x < 0 || x >= (int)image.getWidth())
52 continue; // In case we start off the edge
53 int my = int(start.y + dy * i);
54 int ey = min(my + var + 1, (int)image.getHeight() - 1);
55 int sy = max(my - var, 0);
56 for (int y = sy + 1; y < ey; y++) {
58 if (image.get(x, y) && !image.get(x, y + 1)) {
59 points.push_back(Point(x, y + 0.5f));
62 if (!image.get(x, y) && image.get(x, y + 1)) {
63 points.push_back(Point(x, y + 0.5f));
73 var = int(abs(deviation * length / ydist));
75 float dx = xdist / ydist * skip;
76 bool down = (skip > 0) ^ invert;
79 int steps = int(ydist / skip);
80 for (int i = 0; i < steps; i++) {
82 if (y < 0 || y >= (int)image.getHeight())
83 continue; // In case we start off the edge
84 int mx = int(start.x + dx * i);
85 int ex = min(mx + var + 1, (int)image.getWidth() - 1);
86 int sx = max(mx - var, 0);
87 for (int x = sx + 1; x < ex; x++) {
89 if (image.get(x, y) && !image.get(x + 1, y)) {
90 points.push_back(Point(x + 0.5f, y));
94 if (!image.get(x, y) && image.get(x + 1, y)) {
95 points.push_back(Point(x + 0.5f, y));
105 Line findLine(const BitMatrix& image, Line estimate, bool invert, int deviation, float threshold, int skip) {
106 float t = threshold * threshold;
108 Point start = estimate.start;
109 Point end = estimate.end;
113 findEdgePoints(edges, image, start, end, invert, skip, deviation);
115 int n = edges.size();
117 float xdist = end.x - start.x;
118 float ydist = end.y - start.y;
120 bool horizontal = abs(xdist) > abs(ydist);
123 Line bestLine(start, end); // prepopulate with the given line, in case we can't find any line for some reason
125 for (int i = -deviation; i < deviation; i++) {
129 x1 = start.x - i * ydist / xdist;
131 y1 = start.y - i * xdist / ydist;
135 for (int j = -deviation; j < deviation; j++) {
139 x2 = end.x - j * ydist / xdist;
141 y2 = end.y - j * xdist / ydist;
147 float length = sqrt(dx * dx + dy * dy);
151 for(int k = 0; k < n; k++) {
152 const Point& edge = edges[k];
153 float dist = ((x1 - edge.x) * dy - (y1 - edge.y) * dx) / length;
154 // Similar to least squares method
155 float s = t - dist * dist;
162 bestLine.start = Point(x1, y1);
163 bestLine.end = Point(x2, y2);
171 Point intersection(Line a, Line b) {
172 float dxa = a.start.x - a.end.x;
173 float dxb = b.start.x - b.end.x;
174 float dya = a.start.y - a.end.y;
175 float dyb = b.start.y - b.end.y;
177 float p = a.start.x * a.end.y - a.start.y * a.end.x;
178 float q = b.start.x * b.end.y - b.start.y * b.end.x;
179 float denom = dxa * dyb - dya * dxb;
180 if(denom == 0) // Lines don't intersect
181 return Point(INFINITY, INFINITY);
183 float x = (p * dxb - dxa * q) / denom;
184 float y = (p * dyb - dya * q) / denom;
189 } // namespace EdgeDetector