zxing源码阅读

关于zxing识别中的源码
其中图像做二值化的部分

bool
GlobalHistogramBinarizer::getBlackRow(int y, BitArray& row) const  //image处理的成员函数, y是所在行
{
	int width = _source->width();
	if (row.size() != width)
		row = BitArray(width);
	else
		row.clearBits();

	ByteArray buffer;
	const uint8_t* luminances = _source->getRow(y, buffer); //获取一张图片第y行的数据
	std::array<int, LUMINANCE_BUCKETS> buckets = {};  //static const int LUMINANCE_BUCKETS = 1 << 5;
	for (int x = 0; x < width; x++) {
		int pixel = luminances[x];
		buckets[pixel >> LUMINANCE_SHIFT]++;
	}   //统计每一行像素点,0-255每8个单位为一个区间,类似作直方图
	int blackPoint = EstimateBlackPoint(buckets);
	if (blackPoint >= 0) {
		if (width < 3) {
			// Special case for very small images
			for (int x = 0; x < width; x++) {
				if (luminances[x] < blackPoint) {
					row.set(x);
				}
			}
		}
		else {
			if (luminances[0] < blackPoint)
				row.set(0);
			int left = luminances[0];
			int center = luminances[1];
			for (int x = 1; x < width - 1; x++) {
				int right = luminances[x + 1];
				// A simple -1 4 -1 box filter with a weight of 2.
				//相当于在该行像素上做了-1 4 -1的滤波
				if (((center * 4) - left - right) / 2 < blackPoint) {
					row.set(x);
				}
				left = center;
				center = right;
			}
			if (luminances[width-1] < blackPoint)
				row.set(width-1);
		}//二值化
		return true;
	}
	return false;
}
static int EstimateBlackPoint(const std::array<int, LUMINANCE_BUCKETS>& buckets)
{
	// Find the tallest peak in the histogram.
	auto firstPeakPos = std::max_element(buckets.begin(), buckets.end()); //找到直方图的第一个peak
	int firstPeak = static_cast<int>(firstPeakPos - buckets.begin());
	int firstPeakSize = *firstPeakPos;
	int maxBucketCount = firstPeakSize;

	// Find the second-tallest peak which is somewhat far from the tallest peak.
	int secondPeak = 0;
	int secondPeakScore = 0;
	for (int x = 0; x < LUMINANCE_BUCKETS; x++) {
		int distanceToBiggest = x - firstPeak;
		// Encourage more distant second peaks by multiplying by square of distance.
		int score = buckets[x] * distanceToBiggest * distanceToBiggest;//第二个峰值与第一个峰值距离越大,size越大,得分越高,score = 区间像素总数*距离平方
		if (score > secondPeakScore) {
			secondPeak = x;
			secondPeakScore = score;
		}
	}

	// Make sure firstPeak corresponds to the black peak.
	if (firstPeak > secondPeak) {
		std::swap(firstPeak, secondPeak);
	}

	// If there is too little contrast in the image to pick a meaningful black point, throw rather
	// than waste time trying to decode the image, and risk false positives.
	//如果两个峰值太接近,则识别失败
	if (secondPeak - firstPeak <= LUMINANCE_BUCKETS / 16) {
		return -1;
	}

	// Find a valley between them that is low and closer to the white peak.
	//在两个峰值之间找到第三个峰值,将这个峰值作为二值化的阈值
	int bestValley = secondPeak - 1;
	int bestValleyScore = -1;
	for (int x = secondPeak - 1; x > firstPeak; x--) {
		int fromFirst = x - firstPeak;
		int score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]);
		if (score > bestValleyScore) {
			bestValley = x;
			bestValleyScore = score;
		}
	}

	return bestValley << LUMINANCE_SHIFT;
}
上一篇:(lintcode)第24题 LFU缓存


下一篇:(lintcode)第28题 搜索二维矩阵