Skip to content

Commit 26d088f

Browse files
committed
fix(vendor/kik): prevent possible SIGSEV on arm64 devices when scanning
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 5c01758 commit 26d088f

1 file changed

Lines changed: 62 additions & 61 deletions

File tree

vendor/kik/scanner/src/main/cpp/scan/scanner.cpp

Lines changed: 62 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ static uint64_t getTimestamp()
4040
typedef struct {
4141
double dx;
4242
double dy;
43-
43+
4444
double x;
4545
double y;
46-
46+
4747
double angle;
4848
double dist;
49-
49+
5050
int contourIndex;
5151
int contourSize;
5252
} FinderPoint;
@@ -119,11 +119,11 @@ void dilation(Mat &src, Mat &out, size_t dilation_size)
119119
Mat element = getStructuringElement(MORPH_CROSS,
120120
Size2i(2 * dilation_size + 1, 2 * dilation_size + 1),
121121
Point2i(dilation_size, dilation_size));
122-
122+
123123
dilate(src, out, element);
124124
}
125125

126-
void unsharpMask(cv::Mat &im)
126+
void unsharpMask(cv::Mat &im)
127127
{
128128
cv::Mat tmp;
129129
cv::GaussianBlur(im, tmp, cv::Size(0, 0), 2);
@@ -157,16 +157,16 @@ bool extractFinderPoints(int ellipse_id, bool check_high, RotatedRect inner_ring
157157
// start by masking off the region where we expect to find the finder
158158
// ring (between 1.22 and 1.525 times the size of the inner circle)
159159
Mat finder_point_range = Mat::zeros(whitish.size(), whitish.type());
160-
160+
161161
inner_ring.size.width *= 1.525;
162162
inner_ring.size.height *= 1.525;
163-
163+
164164
START_DEBUG_TIMING(efp_ellipse_region);
165165
ellipse(finder_point_range, inner_ring, Scalar(255, 255, 255), -1);
166-
166+
167167
inner_ring.size.width *= 0.805;
168168
inner_ring.size.height *= 0.805;
169-
169+
170170
ellipse(finder_point_range, inner_ring, Scalar(0, 0, 0), -1);
171171

172172
if (debug) {
@@ -176,7 +176,7 @@ bool extractFinderPoints(int ellipse_id, bool check_high, RotatedRect inner_ring
176176

177177
imwrite(filename, finder_point_range);
178178
}
179-
179+
180180
END_DEBUG_TIMING(timing, efp_ellipse_region);
181181
Point2i last_point;
182182

@@ -195,12 +195,12 @@ bool extractFinderPoints(int ellipse_id, bool check_high, RotatedRect inner_ring
195195

196196
vector<vector<Point2i> > contours;
197197
vector<Vec4i> hierarchy;
198-
198+
199199
// detect all blobs within the candidate region
200200
START_DEBUG_TIMING(efp_contours);
201201
findContours(candidate_region, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE, Point2i(0, 0));
202202
END_DEBUG_TIMING(timing, efp_contours);
203-
203+
204204
// compute the image moments for each blob in the candidate region, we use these
205205
// moments to look and the relative angles between the **centers** of each blob
206206
START_DEBUG_TIMING(efp_moments);
@@ -240,50 +240,50 @@ bool extractFinderPoints(int ellipse_id, bool check_high, RotatedRect inner_ring
240240
START_DEBUG_TIMING(efp_extraction);
241241
for (int i = 0; i < contours.size(); ++i) {
242242
vector<Point2i> &contour = contours[i];
243-
243+
244244
Point2i point = mc[i];
245-
245+
246246
double dist = sqrt(pow(point.x - last_point.x, 2.0) + pow(point.y - last_point.y, 2.0));
247-
247+
248248
if (dist < 2) {
249249
continue;
250250
}
251-
251+
252252
last_point = point;
253-
253+
254254
if (contour.size() > 1) {
255255
if (mc[i].y > 0 && mc[i].x > 0) {
256256
if (finder_point_range.at<char>(mc[i].y, mc[i].x) != 0) {
257257
FinderPoint finder;
258-
258+
259259
finder.x = mc[i].x;
260260
finder.y = mc[i].y;
261-
261+
262262
finder.dx = finder.x - inner_ring.center.x;
263263
finder.dy = finder.y - inner_ring.center.y;
264-
264+
265265
finder.contourIndex = i;
266266

267267
finder.contourSize = contour.size();
268-
268+
269269
finder.dist = sqrt(finder.dx * finder.dx + finder.dy * finder.dy);
270-
270+
271271
finder.angle = atan2(finder.dy, finder.dx);
272-
272+
273273
finder_points.push_back(finder);
274274
}
275275
}
276276
}
277277
}
278278
END_DEBUG_TIMING(timing, efp_extraction);
279-
279+
280280
START_DEBUG_TIMING(efp_filter_and_sort);
281281
if (finder_points.size() > 0) {
282282
// disard small shards that were erroneously picked up
283283
sort(finder_points.begin(), finder_points.end(), compareFinderPointsSize);
284284

285285
int p90_size = finder_points[finder_points.size() * 0.9].contourSize;
286-
286+
287287
for (int i = 0; i < finder_points.size(); ++i) {
288288
if (finder_points[i].contourSize < p90_size / 5) {
289289
finder_points.erase(finder_points.begin() + i);
@@ -316,18 +316,18 @@ bool extractFinderPoints(int ellipse_id, bool check_high, RotatedRect inner_ring
316316
if (finder_points.size() != sizeof(finder_deltas) / sizeof(double) + 1) {
317317
return false;
318318
}
319-
319+
320320
// sort the finder points into a clockwise winding based on the angle of the computed vector
321321
sort(finder_points.begin(), finder_points.end(), compareFinderPoints);
322322
END_DEBUG_TIMING(timing, efp_filter_and_sort);
323-
323+
324324
vector<double> point_deltas(finder_points.size());
325-
325+
326326
START_DEBUG_TIMING(efp_check_ratio);
327327
// compute the relative angles between each neighbouring pair of finder points
328328
for (int j = 0; j < finder_points.size(); ++j) {
329329
point_deltas[j] = finder_points[(j + 1) % finder_points.size()].angle - finder_points[j].angle;
330-
330+
331331
while (point_deltas[j] < 0.0) {
332332
point_deltas[j] += 2 * M_PI;
333333
}
@@ -340,13 +340,13 @@ bool extractFinderPoints(int ellipse_id, bool check_high, RotatedRect inner_ring
340340
// the given starting offset
341341
for (int j = 0; j < point_deltas.size(); ++j) {
342342
bool found = true;
343-
343+
344344
for (int k = 0; k < sizeof(finder_deltas) / sizeof(double); ++k) {
345345
double pointRatio = point_deltas[(j + k) % point_deltas.size()];
346-
346+
347347
double lower_bound = finder_deltas[k] - 0.25;
348348
double upper_bound = finder_deltas[k] + 0.25;
349-
349+
350350
if (pointRatio < lower_bound) {
351351
found = false;
352352
break;
@@ -356,7 +356,7 @@ bool extractFinderPoints(int ellipse_id, bool check_high, RotatedRect inner_ring
356356
break;
357357
}
358358
}
359-
359+
360360
if (found) {
361361
offset = j;
362362
break;
@@ -445,7 +445,7 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
445445

446446
if (out_progress) {
447447
Mat rgb_colour;
448-
448+
449449
cvtColor(greyscale, rgb_colour, COLOR_GRAY2RGB);
450450

451451
progress = rgb_colour;
@@ -479,11 +479,11 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
479479
#endif
480480

481481
Mat contour_mat = whitish.clone();
482-
482+
483483
// extract the contours and blobs from the thresholded image
484484
vector<vector<Point2i> > contours;
485485
vector<Vec4i> hierarchy;
486-
486+
487487
START_DEBUG_TIMING(contours_1);
488488
findContours(contour_mat, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE, Point2i(0, 0));
489489
END_DEBUG_TIMING(timing, contours_1);
@@ -499,16 +499,16 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
499499
imwrite("03_contours.jpg", contour_debug);
500500
}
501501
#endif
502-
502+
503503
// compute the moments of each contour to search for large, roundish, blobs
504504
vector<Moments> mu(contours.size());
505505
vector<Point2f> mc(contours.size());
506-
506+
507507
START_DEBUG_TIMING(moment_pass_1);
508508

509509
// find ellipses
510510
Mat ellipse_boundaries = Mat::zeros(contour_mat.size(), CV_8UC1);
511-
511+
512512
for (int i = 0; i < contours.size(); ++i) {
513513
vector<Point2i> &contour = contours[i];
514514

@@ -531,7 +531,7 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
531531
}
532532

533533
Moments moment = mu[i];
534-
534+
535535
// the contour must be...
536536
// large enough
537537
const double minimum_ellipse_area = 220 * scaling_rate;
@@ -645,7 +645,7 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
645645
#endif
646646

647647
END_DEBUG_TIMING(timing, ellipse_fitting_1);
648-
648+
649649
// only keep edges that share edges with the fitted ellipses
650650
Mat matches_near_ellipses;
651651

@@ -664,7 +664,8 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
664664
for (int j = 0; j < contour.size(); ++j) {
665665
Point2i &point = contour[j];
666666

667-
if (matches_near_ellipses.at<char>(point.y, point.x) != 0) {
667+
if (point.x >= 0 && point.y >= 0 && point.x < matches_near_ellipses.cols && point.y < matches_near_ellipses.rows
668+
&& matches_near_ellipses.at<char>(point.y, point.x) != 0) {
668669
pruned_contour.push_back(point);
669670
}
670671
}
@@ -674,7 +675,7 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
674675

675676
vector<vector<Point2i> > contours2 = pruned_contours;
676677
vector<Vec4i> hierarchy2;
677-
678+
678679
// search the limited edges to find strong ellipse matches
679680
vector<RotatedRect> ellipses;
680681
vector<size_t> contour_indices;
@@ -693,15 +694,15 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
693694

694695
vector<RotatedRect> potential_ellipses;
695696
vector<size_t> potential_contour_indices;
696-
697+
697698
// re-fit the ellipses based on only the filtered points
698699
// and only if the contours have enough points to be useful
699700
// (ellipse fitting requires 5 reference points at a minimum)
700701
START_DEBUG_TIMING(ellipse_fitting_2);
701702
// find all ellipses in the search space by estimating the fit
702703
for (int i = 0; i < contours2.size(); ++i) {
703704
vector<Point2i> &contour = contours2[i];
704-
705+
705706
// the contour must be sufficiently dense
706707
// and the mass of the moment must be large enough
707708
if (contour.size() > 5) {
@@ -752,7 +753,7 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
752753
imwrite("06_candidates.jpg", candidates);
753754
}
754755
#endif
755-
756+
756757
// iterate over each candidate ring and determine if it's really the
757758
// center of a Kik code
758759
START_DEBUG_TIMING(ellipse_search);
@@ -770,12 +771,12 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
770771

771772
size_t dark_count = 0;
772773

773-
for (int j = 0; j < contour.size(); ++j) {
774-
Point2i point = contour[j];
774+
for (auto point : contour) {
775775
int x = 0.9 * (point.x - candidate_center.center.x) + candidate_center.center.x;
776776
int y = 0.9 * (point.y - candidate_center.center.y) + candidate_center.center.y;
777777

778-
if (whitish.at<char>(y, x) == 0) {
778+
if (x >= 0 && y >= 0 && x < whitish.cols && y < whitish.rows
779+
&& whitish.at<char>(y, x) == 0) {
779780
++dark_count;
780781
}
781782
}
@@ -800,7 +801,7 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
800801
if (finder_points.size() != FINDER_POINT_COUNT) {
801802
continue;
802803
}
803-
804+
804805
double current_angle = M_PI / 16 - M_PI / 2;
805806
vector<Point2f> object_finder_points;
806807
vector<Point2f> scene_finder_points;
@@ -811,17 +812,17 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
811812
float modifier = 42;
812813
float offset_x = 195.0;
813814
float offset_y = 195.0;
814-
815+
815816
// create the set of scene points and object points for computing the homography to map
816817
// our exemplar Kik code onto the scene
817818
START_DEBUG_TIMING(generate_scene_points);
818819
for (int j = 0; j < finder_points.size(); ++j) {
819820
object_finder_points.push_back(
820821
Point2f(modifier * 2.025 * cos(current_angle) + offset_x, modifier * 2.025 * sin(current_angle) + offset_y));
821-
822+
822823
current_angle += finder_deltas[j];
823824
}
824-
825+
825826
for (int j = 0; j < finder_points.size(); ++j) {
826827
FinderPoint point = finder_points[(j+offset) % finder_points.size()];
827828
scene_finder_points.push_back(Point2f(point.x, point.y));
@@ -833,29 +834,29 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
833834
START_DEBUG_TIMING(find_homography);
834835
Mat H = findHomography(object_finder_points, scene_finder_points, FM_RANSAC);
835836
END_DEBUG_TIMING(timing, find_homography);
836-
837+
837838
START_DEBUG_TIMING(transform_finder_points);
838839
vector<Point2f> scene_corners(object_finder_points.size());
839-
840+
840841
perspectiveTransform(object_finder_points, scene_corners, H);
841842
END_DEBUG_TIMING(timing, transform_finder_points);
842843

843844
START_DEBUG_TIMING(transform_all_points);
844845
vector<Point2f> all_points;
845846
vector<Point2f> scene_points;
846-
847+
847848
// generate all positions on the Kik code in the object space
848849
for (int r = 1; r < 6; ++r) {
849850
size_t n = 32 + 8 * r;
850-
851+
851852
for (int j = 0; j < n; ++j) {
852853
double angle = j * M_PI / n * 2 - M_PI / 2;
853854
double radius = modifier * ((r + 1) * 0.4 + 1.8);
854-
855+
855856
all_points.push_back(Point2f(radius * cos(angle) + offset_x, radius * sin(angle) + offset_y));
856857
}
857858
}
858-
859+
859860
// map each position in the object-space Kik code on to the scene space
860861
perspectiveTransform(all_points, scene_points, H);
861862
END_DEBUG_TIMING(timing, transform_all_points);
@@ -865,14 +866,14 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u
865866
// we always have the finder pattern in the first 32 bits
866867
memset(scan_data, 0, sizeof(scan_data));
867868
memcpy(scan_data, finder_bytes, sizeof(finder_bytes));
868-
869+
869870
// use the scene-space points to determine the data contained in the Kik code
870871
for (int j = 0; j < scene_points.size(); ++j) {
871872
int x = (int)floor(scene_points[j].x);
872873
int y = (int)floor(scene_points[j].y);
873874

874875
size_t pos = j + 32;
875-
876+
876877
// at each position, if the data is white (black in the case of inverted-colour
877878
// codes), it's a 1, otherwise it's a 0
878879
if (x >= 0 && y >= 0 && x < whitish.cols && y < whitish.rows) {

0 commit comments

Comments
 (0)