// The top right point is actually the corner of a module, which is one of the two black modules
// adjacent to the white module at the top right. Tracing to that corner from either the top left
// or bottom right should work here.
- int dimension = Math.min(transitionsBetween(topLeft, topRight).getTransitions(),
- transitionsBetween(bottomRight, topRight).getTransitions());
- if ((dimension & 0x01) == 1) {
+
+
+ int dimensionTop = transitionsBetween(topLeft, topRight).getTransitions();
+ int dimensionRight = transitionsBetween(bottomRight, topRight).getTransitions();
+
+ if ((dimensionTop & 0x01) == 1) {
// it can't be odd, so, round... up?
- dimension++;
+ dimensionTop++;
}
- dimension += 2;
+ dimensionTop += 2;
+
+ if ((dimensionRight & 0x01) == 1) {
+ // it can't be odd, so, round... up?
+ dimensionRight++;
+ }
+ dimensionRight += 2;
+
+ BitMatrix bits = null;
+ ResultPoint correctedTopRight = null;
+
+ if (dimensionTop >= dimensionRight * 2 || dimensionRight >= dimensionTop * 2){
+ //The matrix is rectangular
+
+ correctedTopRight = correctTopRightRectangular(bottomLeft, bottomRight, topLeft, topRight, dimensionTop, dimensionRight);
+ if (correctedTopRight == null){
+ correctedTopRight = topRight;
+ }
+
+ dimensionTop = transitionsBetween(topLeft, correctedTopRight).getTransitions();
+ dimensionRight = transitionsBetween(bottomRight, correctedTopRight).getTransitions();
+
+ if ((dimensionTop & 0x01) == 1) {
+ // it can't be odd, so, round... up?
+ dimensionTop++;
+ }
+
+ if ((dimensionRight & 0x01) == 1) {
+ // it can't be odd, so, round... up?
+ dimensionRight++;
+ }
+
+ bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimensionTop, dimensionRight);
+
+ } else {
+ //The matrix is square
+
+ int dimension = Math.min(dimensionRight, dimensionTop);
+ //correct top right point to match the white module
+ correctedTopRight = correctTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension);
+ if (correctedTopRight == null){
+ correctedTopRight = topRight;
+ }
- //correct top right point to match the white module
- ResultPoint correctedTopRight = correctTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension);
- if (correctedTopRight == null){
- correctedTopRight = topRight;
- }
+ //We redetermine the dimension using the corrected top right point
+ int dimensionCorrected = Math.max(transitionsBetween(topLeft, correctedTopRight).getTransitions(),
+ transitionsBetween(bottomRight, correctedTopRight).getTransitions());
+ dimensionCorrected++;
+ if ((dimensionCorrected & 0x01) == 1) {
+ dimensionCorrected++;
+ }
- //We redetermine the dimension using the corrected top right point
- int dimension2 = Math.max(transitionsBetween(topLeft, correctedTopRight).getTransitions(),
- transitionsBetween(bottomRight, correctedTopRight).getTransitions());
- dimension2++;
- if ((dimension2 & 0x01) == 1) {
- dimension2++;
+ bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimensionCorrected, dimensionCorrected);
}
- BitMatrix bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimension2);
return new DetectorResult(bits, new ResultPoint[]{topLeft, bottomLeft, bottomRight, correctedTopRight});
}
/**
- * Calculates the position of the white top right module using the output of the rectangle detector
+ * Calculates the position of the white top right module using the output of the rectangle detector for a rectangular matrix
+ */
+ private ResultPoint correctTopRightRectangular(ResultPoint bottomLeft,
+ ResultPoint bottomRight, ResultPoint topLeft, ResultPoint topRight,
+ int dimensionTop, int dimensionRight) {
+
+ float corr = distance(bottomLeft, bottomRight) / (float)dimensionTop;
+ int norm = distance(topLeft, topRight);
+ float cos = (topRight.getX() - topLeft.getX()) / norm;
+ float sin = (topRight.getY() - topLeft.getY()) / norm;
+
+ ResultPoint c1 = new ResultPoint(topRight.getX()+corr*cos, topRight.getY()+corr*sin);
+
+ corr = distance(bottomLeft, topLeft) / (float)dimensionRight;
+ norm = distance(bottomRight, topRight);
+ cos = (topRight.getX() - bottomRight.getX()) / norm;
+ sin = (topRight.getY() - bottomRight.getY()) / norm;
+
+ ResultPoint c2 = new ResultPoint(topRight.getX()+corr*cos, topRight.getY()+corr*sin);
+
+ if (!isValid(c1)){
+ if (isValid(c2)){
+ return c2;
+ }
+ return null;
+ } else if (!isValid(c2)){
+ return c1;
+ }
+
+ int l1 = Math.abs(dimensionTop - transitionsBetween(topLeft, c1).getTransitions()) +
+ Math.abs(dimensionRight - transitionsBetween(bottomRight, c1).getTransitions());
+ int l2 = Math.abs(dimensionTop - transitionsBetween(topLeft, c2).getTransitions()) +
+ Math.abs(dimensionRight - transitionsBetween(bottomRight, c2).getTransitions());
+
+ if (l1 <= l2){
+ return c1;
+ }
+
+ return c2;
+}
+
+/**
+ * Calculates the position of the white top right module using the output of the rectangle detector for a square matrix
*/
private ResultPoint correctTopRight(ResultPoint bottomLeft,
ResultPoint bottomRight,
ResultPoint bottomLeft,
ResultPoint bottomRight,
ResultPoint topRight,
- int dimension) throws NotFoundException {
+ int dimensionX,
+ int dimensionY) throws NotFoundException {
GridSampler sampler = GridSampler.getInstance();
return sampler.sampleGrid(image,
- dimension,
+ dimensionX,
+ dimensionY,
0.5f,
0.5f,
- dimension - 0.5f,
+ dimensionX - 0.5f,
0.5f,
- dimension - 0.5f,
- dimension - 0.5f,
+ dimensionX - 0.5f,
+ dimensionY - 0.5f,
0.5f,
- dimension - 0.5f,
+ dimensionY - 0.5f,
topLeft.getX(),
topLeft.getY(),
topRight.getX(),