?? dmtxregion.c
字號(hào):
matrixRegion->chain.bx1 = 100.0; matrixRegion->chain.by0 = 100.0; matrixRegion->chain.by1 = 100.0; matrixRegion->chain.sz = 100.0; MatrixRegionUpdateXfrms(matrixRegion);}/** * XXX * TODO: this function should really be static --- move "decode" functions into this file * * @param * @return XXX */extern voiddmtxMatrixRegionDeInit(DmtxMatrixRegion *matrixRegion){ if(matrixRegion->array != NULL) free(matrixRegion->array); if(matrixRegion->code != NULL) free(matrixRegion->code); if(matrixRegion->output != NULL) free(matrixRegion->output); memset(matrixRegion, 0x00, sizeof(DmtxMatrixRegion));}/** * XXX * * @param * @return XXX */static voidMatrix3ChainXfrm(DmtxMatrix3 m, DmtxChain *chain){ DmtxMatrix3 mtxy, mphi, mshx, mscxy, msky, mskx; dmtxMatrix3Translate(mtxy, chain->tx, chain->ty); dmtxMatrix3Rotate(mphi, chain->phi); dmtxMatrix3Shear(mshx, chain->shx, 0.0); dmtxMatrix3Scale(mscxy, chain->scx * chain->sz, chain->scy * chain->sz); dmtxMatrix3LineSkewTop(msky, chain->by0, chain->by1, chain->sz); dmtxMatrix3LineSkewSide(mskx, chain->bx0, chain->bx1, chain->sz); dmtxMatrix3Multiply(m, mtxy, mphi); dmtxMatrix3MultiplyBy(m, mshx); dmtxMatrix3MultiplyBy(m, mscxy); dmtxMatrix3MultiplyBy(m, msky); dmtxMatrix3MultiplyBy(m, mskx);}/** * XXX * * @param * @return XXX */static voidMatrix3ChainXfrmInv(DmtxMatrix3 m, DmtxChain *chain){ DmtxMatrix3 mskx, msky, mscxy, mshx, mphi, mtxy; dmtxMatrix3LineSkewSideInv(mskx, chain->bx0, chain->bx1, chain->sz); dmtxMatrix3LineSkewTopInv(msky, chain->by0, chain->by1, chain->sz); dmtxMatrix3Scale(mscxy, 1.0/(chain->scx * chain->sz), 1.0/(chain->scy * chain->sz)); dmtxMatrix3Shear(mshx, -chain->shx, 0.0); dmtxMatrix3Rotate(mphi, -chain->phi); dmtxMatrix3Translate(mtxy, -chain->tx, -chain->ty); dmtxMatrix3Multiply(m, mskx, msky); dmtxMatrix3MultiplyBy(m, mscxy); dmtxMatrix3MultiplyBy(m, mshx); dmtxMatrix3MultiplyBy(m, mphi); dmtxMatrix3MultiplyBy(m, mtxy);}/** * XXX * * @param * @return XXX */static voidMatrixRegionUpdateXfrms(DmtxMatrixRegion *matrixRegion){ Matrix3ChainXfrm(matrixRegion->raw2fit, &(matrixRegion->chain)); Matrix3ChainXfrmInv(matrixRegion->fit2raw, &(matrixRegion->chain));}/** * XXX * * @param * @return XXX */static intMatrixRegionAlignFinderBars(DmtxMatrixRegion *matrixRegion, DmtxDecode *decode, DmtxEdgeFollower *f0, DmtxEdgeFollower *f1){ int success; float v1Length; float v2Length; DmtxFinderBar bar; DmtxEdgeFollower *fTmp; DmtxRay2 rPrimary, rSecondary; DmtxVector2 pMin, pTmp; DmtxVector2 v1, v2; DmtxMatrix3 m; DmtxChain chain;/* XXX comment these cases bettercount 1st 2nd 0 0 return false 1 1 colinear? yes: decide which is primary (longer secondary) verify other finder bar is co-linear no: finder bars are known 1 0 11 0 primary is known verify that secondary is long enough 0 1 0 11 primary is known verify that secondary is long enough*/ // Ensure that no secondary line is defined unless primary line is also defined assert((f0->line1.isDefined) ? f0->line0.isDefined : 1); assert((f1->line1.isDefined) ? f1->line0.isDefined : 1); // We need at least 2 finder bar candidates to proceed if(f0->line0.isDefined + f0->line1.isDefined + f1->line0.isDefined + f1->line1.isDefined < 2) { return DMTX_FALSE; } // One direction contains both possible finder bar candidates (rare) else if(f0->line0.isDefined + f1->line0.isDefined == 1) { fTmp = (f0->line0.isDefined) ? f0 : f1; rPrimary = fTmp->line0; // Set primary to the defined one rSecondary = fTmp->line1; // Set secondary to the defined one's dog-leg } // Each direction contains a finder bar candidate else { // Close to -1.0 means colinear (but opposite) if(dmtxVector2Dot(&(f0->line0.v), &(f1->line0.v)) < -0.99) { if(f0->line1.isDefined * (f0->line1.tMax - f0->line1.tMin) > f1->line1.isDefined * (f1->line1.tMax - f1->line1.tMin)) { // Primary is combination of both line0's (careful about direction / tMax handling) rPrimary = f1->line0; dmtxPointAlongRay2(&pMin, &(f0->line0), f0->line0.tMax); rPrimary.tMin = dmtxDistanceAlongRay2(&rPrimary, &pMin); rSecondary = f0->line1; } else { // Primary is combination of both line0's (careful about direction / tMax handling) rPrimary = f0->line0; dmtxPointAlongRay2(&pMin, &(f1->line0), f1->line0.tMax); rPrimary.tMin = dmtxDistanceAlongRay2(&rPrimary, &pMin); rSecondary = f1->line1; } } else { // Set primary and secondary to line0's arbitrarily rPrimary = f0->line0; rSecondary = f1->line0; } } // Check if we have to valid lines if(rPrimary.isDefined == 0 || rSecondary.isDefined == 0) { return DMTX_FALSE; } else if(rPrimary.tMax - rPrimary.tMin < 15 || rSecondary.tMax - rSecondary.tMin < 15) { return DMTX_FALSE; } // Can't check lengths yet because length should be calculated from the // true intersection of both lines // Find intersection of 2 chosen rays success = dmtxRay2Intersect(&(bar.p0), &rPrimary, &rSecondary); if(!success) { return DMTX_FALSE; } dmtxPointAlongRay2(&(bar.p2), &rPrimary, rPrimary.tMax); dmtxPointAlongRay2(&(bar.p1), &rSecondary, rSecondary.tMax); dmtxVector2Sub(&v1, &bar.p1, &bar.p0); dmtxVector2Sub(&v2, &bar.p2, &bar.p0); v1Length = dmtxVector2Mag(&v1); v2Length = dmtxVector2Mag(&v2); // Check that both lines are at least 10 pixels in length if(v1Length < 10 || v2Length < 10) {// fprintf(stdout, "Reject: At least one finder bar is too short.\n"); return DMTX_FALSE; } // Check matrix is not too "flat" else if(min(v1Length, v2Length) / max(v1Length, v2Length) < 0.2) {// fprintf(stdout, "Reject: Candidate region is too \"flat\" (%g).\n",// min(v1Length, v2Length) / max(v1Length, v2Length)); return DMTX_FALSE; } // normalize(dir1) and normalize(dir2) dmtxVector2Norm(&v1); dmtxVector2Norm(&v2); // Check that finder bars are not colinear if(fabs(dmtxVector2Dot(&v1, &v2)) > cos(20.0*M_PI/180.0)) {// fprintf(stdout, "Reject: Finder bars are too colinear.\n"); return DMTX_FALSE; } // XXX This is where we draw the 3 squares on the first pane: Replace with plotPoint callback if(decode && decode->plotPointCallback) { (*(decode->plotPointCallback))(bar.p0, 1, 1, DMTX_DISPLAY_SQUARE); (*(decode->plotPointCallback))(bar.p1, 1, 1, DMTX_DISPLAY_SQUARE); (*(decode->plotPointCallback))(bar.p2, 1, 1, DMTX_DISPLAY_SQUARE); } // Check for clockwise/ccw order of points and flip if necessary if(dmtxVector2Cross(&v2, &v1) < 0.0) { pTmp = bar.p1; bar.p1 = bar.p2; bar.p2 = pTmp; } chain.tx = -bar.p0.X; chain.ty = -bar.p0.Y; chain.phi = 0.0; chain.shx = 0.0; chain.scx = chain.scy = 1.0; chain.bx0 = chain.bx1 = chain.by0 = chain.by1 = chain.sz = 1.0; Matrix3ChainXfrm(m, &chain); dmtxMatrix3VMultiply(&pTmp, &bar.p2, m); chain.phi = -atan2(pTmp.Y, pTmp.X); Matrix3ChainXfrm(m, &chain); dmtxMatrix3VMultiply(&pTmp, &bar.p2, m); chain.scx = 1.0/pTmp.X; dmtxMatrix3VMultiply(&pTmp, &bar.p1, m); assert(pTmp.Y > DMTX_ALMOST_ZERO); chain.shx = -pTmp.X / pTmp.Y; chain.scy = 1.0/pTmp.Y; chain.bx0 = chain.bx1 = chain.by0 = chain.by1 = chain.sz = 100.0; // Update transformations now that finders are set matrixRegion->chain = chain; MatrixRegionUpdateXfrms(matrixRegion); // Now matrixRegion contains our best guess. Next tighten it up. if(decode && decode->buildMatrixCallback2) (*(decode->buildMatrixCallback2))(&bar, matrixRegion); return DMTX_TRUE;}/** * XXX * * @param * @return XXX */static intMatrixRegionAlignTop(DmtxMatrixRegion *matrixRegion, DmtxDecode *decode){ double t, m; double stepSize; int gapCount = 0, gapLength = 0, maxGapLength = 0; DmtxVector2 p0, px0, px1; DmtxColor3 color; DmtxMatrix3 s, sInv, sReg, sRegInv, m0, m1; DmtxVector2 prevHit, prevStep, highHit, highHitX; dmtxMatrix3LineSkewTop(m0, 100.0, 75.0, 100.0); dmtxMatrix3Scale(m1, 1.25, 1.0); dmtxMatrix3Multiply(s, m0, m1); dmtxMatrix3Multiply(sReg, matrixRegion->raw2fit, s); dmtxMatrix3LineSkewTopInv(m0, 100.0, 75.0, 100.0); dmtxMatrix3Scale(m1, 0.8, 1.0); dmtxMatrix3Multiply(sInv, m1, m0); dmtxMatrix3Multiply(sRegInv, sInv, matrixRegion->fit2raw); if(decode && decode->buildMatrixCallback3) (*(decode->buildMatrixCallback3))(sRegInv); // Determine step size (90% of rough pixel length) px0.X = 0.0; px0.Y = 0.0; px1.X = 0.0; px1.Y = 100.0; dmtxMatrix3VMultiplyBy(&px0, sRegInv); dmtxMatrix3VMultiplyBy(&px1, sRegInv); dmtxVector2SubFrom(&px1, &px0); stepSize = dmtxVector2Mag(&px1); assert(stepSize > DMTX_ALMOST_ZERO); stepSize = 0.9 * (100.0/stepSize); p0.X = 0.0; p0.Y = 100.0; prevStep = prevHit = p0; highHit.X = highHit.Y = 100.0; // XXX add this for safety in case it's not found while(p0.X < 100.0 && p0.Y < 300.0) { // XXX cap rise at 300.0 to prevent infinite loops dmtxMatrix3VMultiply(&px0, &p0, sRegInv); dmtxColor3FromImage(&color, &(decode->image), px0.X, px0.Y); t = dmtxDistanceAlongRay3(&(matrixRegion->gradient.ray), &color); if(decode && decode->xfrmPlotPointCallback) (*(decode->xfrmPlotPointCallback))(px0, sReg, 4, DMTX_DISPLAY_POINT); // Bad notation whereby: // prevStep captures every little step // prevHit captures the most recent edge boundary detection // Need to move upward if(t > matrixRegion->gradient.tMid) { // Need to move up, and previous move was right if(p0.X - prevStep.X > DMTX_ALMOST_ZERO) { if(gapLength > 2*maxGapLength) { maxGapLength = gapLength; gapCount = 1; } else if(gapLength > maxGapLength/2) { gapCount++; } gapLength = 0; // no matter what, reset gapLength } prevStep = p0; p0.Y += stepSize; } // Need to advance to the right else { // Need to move right, and previous step was up if(fabs(p0.Y - prevStep.Y) > DMTX_ALMOST_ZERO) { // If it has been a while since previous hit if(p0.X - prevHit.X >= 3) { highHit = p0; highHitX = px0; } // Recent had a hit else { prevHit = p0;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -