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

📄 hough.h

📁 Hough变换c语言代码
💻 H
字号:
/********************************************************************* * This file is part of the PRAPI library. * * Copyright (C) 2001-2002 Topi M鋏np滗 * Copyright (C) 2001 Jaakko Viertola * All rights reserved. * * This program is free software. You can redistribute and/or modify * it under the terms of the free software licence found in the * accompanying file "COPYING". The licence terms must always be * redistributed with this source file. The above copyright notice * must be reproduced in all modified and unmodified copies of this * source file. * * $Revision: 1.7 $ *********************************************************************/#ifndef _HOUGH_H#define _HOUGH_H#include "../ImageTransform.h"#include "../graphics/Graphics.h"#include "../graphics/Point.h"#include <Matrix.h>#include <Math.h>#include <math.h>#include <functional>namespace prapi { namespace transforms {	/**	 * Linear Hough transform. Detects lines in images. Lines are	 * paramerized by their slope (degrees, zero at positive x axis,	 * growing couter-clockwise) and distance to the origin (pixels),	 * resulting in a two-dimensional transformation domain. In the	 * transformation domain, columns represent different slopes and	 * rows different distances to the origin. The origin of the domain	 * is at the center of the image. The quantization of the	 * transformation domain is user-specifiable. The linear Hough	 * transform can be though of as an image-to-image transform as it	 * effectively produces an image as output.	 **/	template <class T, class U> class LinearHough : public ImageTransform<T,U>	{	public:		/**		 * Create an instance of the linear Hough transform. There are two		 * parameters that need to be initialized. The threshold will be		 * intialized to zero and the size of the transformation result		 * will be intialized to 180x180.		 *		 * @param threshold the value with which the matrix will be thresholded.		 * @param maxRadius the number of rows in the transformed matrix		 *                  (quantization can be made for this parameter).		 * @param maxAngle the number of columns in the transformed matrix		 *                  (quantization can be made for this parameter).		 **/		LinearHough(U threshold = 0, int maxRadius = 180, int maxAngle = 180) :			_threshold(threshold),_iRadius(maxRadius),_iAngle(maxAngle){}		virtual ~LinearHough(){}		/**		 * Transform an image.		 **/		util::Matrix<T> getTransformedImage(const util::Matrix<U>& mat) throw (ImageTransformException&);		/**		 * Set the transformed matrix size. (Maximum radius in the		 * parametric representation.)		 **/		void setMaxRadius(int radius){_iRadius=radius;}		/**		 * Get the maximum radius.		 **/		int getMaxRadius() const {return _iRadius;}		/**		 * Set the transformed matrix size. (Maximum angle in the		 * parametric representation.)		 **/		void setMaxAngle(int angle){_iAngle=angle;}		/**		 * Get the maximum angle.		 **/		int getMaxAngle() const {return _iAngle;}		/**		 * Set a new threshold for Hough transform.		 **/		void setThreshold(U threshold){_threshold =  threshold;}		/**		 * Get the current threshold.		 **/		U getThreshold(){return _threshold;}			private:		/**		 * The value of threshold.		 **/		U _threshold;		/**		 * The sizes of Transformed Matrix.		 **/		int _iRadius;		int _iAngle;			};		template <class T, class U> util::Matrix<T> LinearHough<T,U>::getTransformedImage(const util::Matrix<U>& mat)		throw (ImageTransformException&)	{		int rows = mat.getRows();		int cols = mat.getColumns();				// check the nececary values		if(_iRadius <= 0 || _iAngle <= 0)			throw ImageTransformException("LinearHough::getTransformedImage(const Matrix&): The size of the transformation must be greater than zero.");		else if(rows == 0 || cols == 0)			throw ImageTransformException("LinearHough::getTransformedImage(const Matrix&): The size of the input matrix must be greater than zero.");					double centerX = cols/2.0; // the center point of X coordinates		double centerY = rows/2.0; // the center point of Y coordinates		// the conversion values degs to rads and scale the omega		// the calculation is = (M_PI/180.0)*(180.0/_iAngle)=M_PI/_iAngle.		double conversion = M_PI/double(_iAngle); // the conversion value degs to rads					double max = sqrt(rows*rows+cols*cols);		double scaleRadius = double((_iRadius)/max);		util::Matrix<T> result(_iRadius,_iAngle);		//graphics::MemoryGraphics<T> g(result);		util::List<double> cosAngleValues(_iAngle);		util::List<double> sinAngleValues(_iAngle); //for optimization		// calculate first the values of angles		for(int omega=0; omega<_iAngle; omega++)			{				sinAngleValues += sin(double(omega)*conversion-M_PI/2);				cosAngleValues += cos(double(omega)*conversion-M_PI/2);			}				// go through the matrix		const U* data = mat.getData();		for(int y=0;y<rows;y++)			for(int x=0;x<cols;x++,data++)				{					if(*data > _threshold)						{							double coordX = x - centerX;							double coordY = centerY - y;							for(int omega=0; omega<_iAngle; omega++)								{									int r = int(scaleRadius*(coordX*cosAngleValues[omega] + coordY*sinAngleValues[omega])+0.5);									if (r >= 0 && r < _iRadius)										result(r,omega) += T(*data);								}						}				}		return result;	}	/**	 * Circular Hough transform. The circular Hough transform detects	 * circles in images. Circles are parametrized with their center	 * pixel (R,C) and radius (r), resulting in a three-dimensional	 * transform domain. The transformation method however returns a	 * two-dimensional matrix. The third dimension is "virtualized" by	 * copying two-dimensional domains on top of each other as shown in	 * the following example:	 *	 * <pre>	 * Two-dimensional transform domain:	 *	 *     +------> C	 *     |	 *     |	 *     |	 *     V	 *     R	 *	 * Three-dimensional domain:	 *	 *     +------> C	 *     |	 * r=1 |	 *     |	 *    ...	 *     |	 * r=N |	 *     |	 *     V	 *     R	 * </pre>	 *	 * The circular Hough transform takes two forms. In the default	 * form, input images are represented as gradient magnitude (edge)	 * images. The transformation cannot be guided by gradient	 * direction, which results in inaccurate and somewhat slow	 * operation. If the U template parameter is of type	 * Point&lt;double&gt;, each pixel in the image is treated as a	 * gradient angle-magnitude pair. This kind of images can be	 * obtained for example from DifferentialEdgeDetector. Given the	 * gradient information, the transform can be optimized quite a lot.	 **/	template <class T, class U> class CircularHough : public ImageTransform<T,U>	{	public:		/**		 * Create an instance of the circular Hough transform. The		 * transform detects circles with a number of different radii,		 * specified with the start/endRadius parameters and radiusStep. 		 * The total number of 2-D transformation domains stacked on each		 * other is (endRadius - startRadius)/radiusStep.		 *		 * @param magnitudeThreshold in transformation, use only pixels		 * with gradient magnitudes not less than this value.		 * @param startRadius find circles with radii not smaller than this value		 * @param endRadius find circles with radii not larger than this		 * value. If endRadius is set to a number less than 1, all circles		 * up to the largest possible one are found.		 * @param radiusStep create a new 2-D transformation domain for		 * each this many pixels.		 **/		CircularHough(T magnitudeThreshold,									int startRadius=1, int endRadius=-1, double radiusStep=1) :			_threshold(magnitudeThreshold),			_iStartRadius(startRadius), _iEndRadius(endRadius), _dRadiusStep(radiusStep) {}		/**		 * Set the threshold.		 **/		void setThreshold(T threshold) { _threshold = threshold; }		/**		 * Get the current threshold.		 **/		T getThreshold() const { return _threshold; }		/**		 * Set the radii that the transform looks for, and the sampling		 * step.		 **/		void setRadii(int start, int end, double step)		{			_iStartRadius = start; _iEndRadius = end;			_dRadiusStep = step;		}		/**		 * Get the start radius.		 **/		int getStartRadius() { return _iStartRadius; }		/**		 * Get the end radius.		 **/		int getEndRadius() { return _iEndRadius; }		/**		 * Get the sampling step.		 **/		double getRadiusStep() { return _dRadiusStep; }				/**		 * Transform a gradient image.		 **/		util::Matrix<T> getTransformedImage(const util::Matrix<U>& mat) throw (ImageTransformException&);	private:		T _threshold;		int _iStartRadius, _iEndRadius;		double _dRadiusStep;	};		/**	 * The circular Hough transform for gradient images. The algorithm	 * used here is a modified version of the one typically found in	 * computer vision textbooks. Instead of blindly trusting the given	 * gradient directions, an error term can be given to indicate the	 * trustworthness of the gradient estimates. Since gradients are	 * typically measured with 3x3 masks, they cannot be very accurate. 	 * When a measure of the angular error is involved, the	 * transformation method assumes the real value of the gradient is	 * normally distributed around the given angle estimate. The width	 * of the distribution is dependent on the error estimate.	 **/	template <class T> class CircularHough<T, graphics::Point<double> > : public ImageTransform<T, graphics::Point<double> >	{	public:		/**		 * Create an instance of the circular Hough transform. The		 * transform detects circles with a number of different radii,		 * specified with the start/endRadius parameters and radiusStep. 		 * The total number of 2-D transformation domains stacked on each		 * other is (endRadius - startRadius)/radiusStep.		 *		 * @param magnitudeThreshold in transformation, use only pixels		 * with gradient magnitudes not less than this value.		 * @param startRadius find circles with radii not smaller than this value		 * @param endRadius find circles with radii not larger than this		 * value. If endRadius is set to a number less than 1, all circles		 * up to the largest possible one are found.		 * @param radiusStep create a new 2-D transformation domain for		 * each this many pixels.		 * @param gradientError an estimate of the error in your gradient		 * measurements (in radians). This value defines the range the		 * real gradients will "most likely" fall into, given a gradient		 * estimate. The transform assumes the real gradient is somewhere		 * in the direction of the estimate +- gradientError.		 **/		CircularHough(double magnitudeThreshold,									int startRadius=1, int endRadius=-1, double radiusStep=1,									double gradientError=0) :			_dThreshold(magnitudeThreshold),			_iStartRadius(startRadius), _iEndRadius(endRadius), _dRadiusStep(radiusStep),			_dGradientError(gradientError) {}		/**		 * Set the threshold.		 **/		void setThreshold(double threshold) { _dThreshold = threshold; }		/**		 * Get the current threshold.		 **/		double getThreshold() const { return _dThreshold; }		/**		 * Set the radii that the transform looks for, and the sampling		 * step.		 **/		void setRadii(int start, int end, double step)		{			_iStartRadius = start; _iEndRadius = end;			_dRadiusStep = step;		}		/**		 * Get the start radius.		 **/		int getStartRadius() { return _iStartRadius; }		/**		 * Get the end radius.		 **/		int getEndRadius() { return _iEndRadius; }		/**		 * Get the sampling step.		 **/		double getRadiusStep() { return _dRadiusStep; }		/**		 * Set the gradient error estimate.		 **/		void setGradientError(double error) { _dGradientError = error; }		/**		 * Get the gradient error estimate.		 **/		double getGradientError() { return _dGradientError; }				/**		 * Transform a gradient image.		 **/		util::Matrix<T> getTransformedImage(const util::Matrix<graphics::Point<double> >& mat) throw (ImageTransformException&);	private:		double _dThreshold;		int _iStartRadius, _iEndRadius;		double _dRadiusStep;		double _dGradientError;	};	template <class T, class U> util::Matrix<T> CircularHough<T,U>::getTransformedImage(const util::Matrix<U>& mat)		throw (ImageTransformException&)	{		int rows =  mat.getRows();		int cols =  mat.getColumns();		int radEnd = _iEndRadius > 0 ? _iEndRadius : maximum(rows, cols)/2;		if (_iStartRadius > _iEndRadius)			throw ImageTransformException("CircularHough::getTransformedImage(const Matrix&): End radius must be larger that start radius.");		int radii = int(double(radEnd - _iStartRadius) / _dRadiusStep) + 1;		util::Matrix<double> result(rows * radii, cols);		graphics::MemoryGraphics<double> transform(result);		graphics::Rectangle<int> rect(0, 0, cols, rows);		transform.setClip(&rect);		transform.setDrawMode(DRAWMODE_PLUS);		int r,c;		AllItems(r,c,mat)			{				T magnitude = mat(r,c);				if (magnitude < _threshold)					continue;				transform.setColor(magnitude);				for (int i=0; i<radii; i++)					{						transform.drawCircle((double)c, (double)r, _iStartRadius + _dRadiusStep*i);						transform.translate(0, rows);					}				//Shift drawing window back to origin				transform.translate(0, -radii*rows);			}		return result;	}	}}#endif

⌨️ 快捷键说明

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