⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bars2symupc.cpp

📁 barcode readers [ from Image]
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			}
		    (*pResult)[i] = sum / sumWeights;
		}
		Mem::Copy((TAny*) vector, (TAny*) &(*pResult)[0], nLength*sizeof(TReal));
		CleanupStack::PopAndDestroy(pResult);
	}

	void CBars2SymUpc::BuildLeftSideMaskL(Code& code, TInt16*& pnMask, TInt &width)
	{
		TReal pfMask[MidOffset + MidWidth];
		width = MidOffset + MidWidth;
		// build left mask
		pfMask[0] = -1.0;
		pfMask[1] = 1.0;
		pfMask[2] = -1.0;
		TInt d;
		// add digit mask
		for (d=0; d<Digits; d++) {
			Mem::Copy((TAny*) &pfMask[LeftWidth + d*DigitWidth],
				(TAny*) &iDigitCodes[code[d]][0],
				DigitWidth * sizeof(TReal));
		}
		// add right mask
		pfMask[MidOffset] = -1.0;
		pfMask[MidOffset+1] = 1.0;
		pfMask[MidOffset+2] = -1.0;
		pfMask[MidOffset+3] = 1.0;
		pfMask[MidOffset+4] = -1.0;
		BlurPatternL(pfMask, width);
		pnMask = new (ELeave) TInt16 [width];
		// note code below can't leave 
		NormalizePattern(
			pfMask, 
			width,
			pnMask,
			true,
			true);
	}

	void CBars2SymUpc::BuildRightSideMaskL(Code& code, TInt16*& pnMask, TInt &width)
	{
		TReal pfMask[MidWidth + Digits*DigitWidth + RightWidth];
		width = MidWidth + Digits*DigitWidth + RightWidth;
		// build mid mask
		pfMask[0] = -1.0;
		pfMask[1] = 1.0;
		pfMask[2] = -1.0;
		pfMask[3] = 1.0;
		pfMask[4] = -1.0;
		TInt d;
		// add digit mask -- reversed because of b/w reversal on right
		for (d=0; d<Digits; d++) {
			TInt i;
			for (i=0; i<DigitWidth; i++) {
				pfMask[MidWidth + d*DigitWidth + i] = -iDigitCodes[code[d]][i];
			}
		}
		// add right mask
		TInt rightOffset = MidWidth + Digits*DigitWidth;
		pfMask[rightOffset] = -1.0;
		pfMask[rightOffset+1] = 1.0;
		pfMask[rightOffset+2] = -1.0;
		BlurPatternL(pfMask, width);
		pnMask = new (ELeave) TInt16 [width];
		// note code below can't leave 
		NormalizePattern(
			pfMask, 
			width,
			pnMask,
			true,
			true);
	}

	void CBars2SymUpc::ClearHash()
	{
		iHashLeft->Clear();
		iHashRight->Clear();
		if (iCodes) {
			int i;
			for (i=0; i<iCodes->Count(); i++) {
				delete iCodes->At(i);
			}
			iCodes->Reset();
		}
	}

	void CBars2SymUpc::ComputeCoefficientsL()
	{
		ipfCoeff = new (ELeave) CArrayFixFlat<TReal>(128);
		const TReal threshold = 0.05;
		// = Sqrt(2*Pi)
		const TReal Sqrt2Pi = 2.506628274631000;
		TReal denom1 = 1.0 / (Sqrt2Pi * ifSigma);
		TReal denom2 = 1.0 / (2.0 * ifSigma * ifSigma);
		TInt x = 0;
		TReal coeff;
		do {
			TReal exp;
			Math::Exp(exp, -x * x * denom2);
			coeff = denom1 * exp;
			ipfCoeff->AppendL(coeff);
			x += 1;
		} while (coeff > threshold); // track through end of tail
		// now normalize so the sum is 1, taking into account 
		// the symmetric pattern of the weights, of which we've
		// computed one side
		TReal sum = ipfCoeff->At(0);
		TInt i;
		for (i=1; i<ipfCoeff->Count(); i++) {
			sum += ipfCoeff->At(i) * 2;
		}
		for (i=0; i<ipfCoeff->Count(); i++) {
			ipfCoeff->At(i) /= sum;
		}
	}

	TInt32 CBars2SymUpc::Convolve(
		IGrayIndex index, 
		TInt16 *pnWeights, 
		TInt nLength, 
		TInt nPixelsPerBar, 
		TInt nRow, 
		TInt nPos)
	{
		TInt32 nConv = 0;
		TInt j;
		for (j=0; j<nLength; j++) {
			TInt k;
			for (k=0; k<nPixelsPerBar; k++) {
				nConv += TInt32(index[nRow][nPos + j*nPixelsPerBar + k]) * TInt32(pnWeights[j]);
			}
		}
		return nConv;
	}

	TInt32 CBars2SymUpc::Convolve(
		CArray<unsigned char> &row,
		TInt16 *pnWeights, 
		TInt nLength, 
		TInt nPixelsPerBar, 
		TInt nCol)
	{
		TInt32 nConv = 0;
		TInt j;
		for (j=0; j<nLength; j++) {
			TInt k;
			for (k=0; k<nPixelsPerBar; k++) {
				nConv += TInt32(row[nCol + j*nPixelsPerBar + k]) * TInt32(pnWeights[j]);
			}
		}
		return nConv;
	}

	/*
	    Input: a rectified and normalized image of a UPC barcode.
		Output: the UPC barcode and a measure of the "goodness" of the
		    match between the barcode and its image.

		Make guesses at the left and right barcodes for each row.
		For each reasonably popular guess at the left barcode, 
			form a mask based on its digits and convolve it with 
			a vertically average of the barcode image, storing the 
			convolution result.
		Repeat this with each reasonably popular guess at the right barcode.
		For each pair of guesses at the left and right barcodes, 
		    check to see if the pair passes the check digit test. 
			If it does, take its combined convolution result, and 
			compare it with the best convolution result so far. 
			If it is better, this pair is the new best guess at the barcode.
	*/
	IMPORT_C bool CBars2SymUpc::DecodeL(
				CImage image, 
				CBars2Sym::CodeType*& pCode,
				TInt32 &goodness)
	{
		pCode = NULL; // no return
		IImageSize size(image);
		int pixelsPerBar = size.Width() / TotalWidth;

		TInt avgLeftEdge;
		// estimate the barcodes on the left and right side
		// for each row in the image and store them into hash
		// tables
		EstimateBarcodesL(image, avgLeftEdge);
		// form the vertical average of the image for verifying
		// the codes
		CVerticalAverage *pAvg = CVerticalAverage::NewL();
		CleanupStack::PushL(pAvg);
		CArray<unsigned char> *pSum;
		pAvg->DoItL(image, pSum);
		CleanupStack::PopAndDestroy(pAvg);
		CleanupStack::PushL(pSum);
		CArrayFixFlat<CodeConv> *pLeftCodes;
		// take the most common left barcodes and estimate their
		// match with the left side of the average
		/* 
		   The point of the code below is that EstimateBarcodesL 
		   does not use an exact test. As we form the barcode guesses 
		   in EstimateBarcodesL, we generate the next digit by testing 
		   all pairs combined with the previous digit. This forms the 
		   best guess at a digit by taking into account the blurring 
		   that results from the digit to the left, but ignores the 
		   blurring that results from the digit to the right. So we 
		   need a way to weed out those guesses where the inaccuracy 
		   of considering just pairs of digits from left to right 
		   results in a bad result. When we form the complete digit 
		   mask in GrabBestBarcodesL we blur both to the left and right, 
		   so that the match estimate is more exact. Also, by convolving 
		   with a vertically averaged barcode image, we eliminate as much 
		   noise as possible.
		   */
		if (!GrabBestBarcodesL(*iHashLeft, pSum, size.Height(), pixelsPerBar, avgLeftEdge, pLeftCodes, true)) {
			CleanupStack::PopAndDestroy(pSum);
			return false;
		}
		CleanupDeletePushL(pLeftCodes);

		CArrayFixFlat<CodeConv> *pRightCodes;
		// take the most common right barcodes and estimate their
		// match with the right side of the image
		if (!GrabBestBarcodesL(*iHashRight, pSum, size.Height(), pixelsPerBar, avgLeftEdge, pRightCodes, false)) {
			CleanupStack::PopAndDestroy(pLeftCodes);
			CleanupStack::PopAndDestroy(pSum);
			return false;
		}
		CleanupDeletePushL(pRightCodes);

		goodness = KMinTInt32;
		pCode = NULL;
		TInt nLeft;
		// combine the left and right barcode estimates
		// and verify the check digit. Maximize the match
		// over all pairs of left and right barcodes.
		for (nLeft = 0; nLeft < pLeftCodes->Count(); nLeft++) {
			TInt nRight;
			for (nRight = 0; nRight < pRightCodes->Count(); nRight++) {
				TInt32 thisGoodness = (*pLeftCodes)[nLeft].Conv() + (*pRightCodes)[nRight].Conv();
				if (thisGoodness > goodness) {
					TBuf8<Digits*2> completeCode;
					completeCode.Append((*pLeftCodes)[nLeft].Code());
					completeCode.Append((*pRightCodes)[nRight].Code());
					if (VerifyCheckDigit(completeCode)) {
						if (pCode) {
							delete pCode;
						}
						pCode = TurnDigitsToText(completeCode);
						goodness = thisGoodness;
					}
				}
			}
		}
		CleanupStack::PopAndDestroy(pRightCodes);
		CleanupStack::PopAndDestroy(pLeftCodes);
		CleanupStack::PopAndDestroy(pSum); 
		return (pCode != NULL);
	}

	TBool CBars2SymUpc::EstimateBarcodesL(CImage image, TInt &avgLeftEdge)
	{
		ClearHash();
		IImageSize size(image);

		int pixelsPerBar = size.Width() / TotalWidth;
		TInt row;
		TInt sumLeftEdge = 0;
		for (row = 0; row<size.Height(); row++) {
			TInt nOffset = EstimateLeftEdge(image, row);
			if (nOffset < 0) {
				return false;
			}
			sumLeftEdge += nOffset;
			TBuf8<Digits> code;
			EstimateCodeLeftL(image, row, nOffset, code);
			if (iHashLeft->Find((Code*)&code[0])) {
				iHashLeft->Value() += 1;
			} else {
				TBuf8<Digits> *pCode = new (ELeave) TBuf8<Digits>;
				pCode->Copy(code);
				iCodes->AppendL(pCode); // so it gets deleted later
				iHashLeft->AddL((Code*)&(*pCode)[0], 1);
			}
            EstimateCodeRightL(image, row, nOffset + MidOffset * pixelsPerBar, code);
			if (iHashRight->Find((Code*)&code[0])) {
				iHashRight->Value() += 1;
			} else {
				TBuf8<Digits> *pCode = new (ELeave) TBuf8<Digits>;
				pCode->Copy(code);
				iCodes->AppendL(pCode); // so it gets deleted later
				iHashRight->AddL((Code*)&(*pCode)[0], 1);
			}
		}
		avgLeftEdge = sumLeftEdge / size.Height();
		return true;
	}

	/*
		The guesses at the left barcodes are made here. 
		CBars2SymUpc::BuildLeftSideMaskL has built one hundred masks, one for each 
		of the digit pairs 00, 01, 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -