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

📄 toolsimagefilter.h

📁 C++ image processing.Mainly it occupies some filters to detect some prperties of image. Release.
💻 H
字号:
#ifndef ToolsImageFilter_h
#define ToolsImageFilter_h

/* 

This "SOFTWARE" is a free software.

You are allowed to download, use, modify and redistribute this software.
The software is provided "AS IS" without warranty of any kind.

Copyright: University of Koblenz-Landau, Dirk Balthasar

*/

#include <ToolsImage.h>
namespace tools
{

	/// \author Dirk Balthasar (private)
	/// help class for FilterKuwaharaNagaoGeneric
	/// replace sector with lowest variance by mean of r,g,b
	template <class ImageType, class AccessRGB>
	class FilterKuwaharaNagaoReplacePixelMeanRGB
	{
		public:
		void Replace(ImageType &Input, ImageType &Output, int x, int y, tools::CROI &ROI, float mr, float mg, float mb)
		{
			Output(x,y)	= AccessRGB::PackRGB(mr, mg, mb);
		}
	};

	/// \author Dirk Balthasar (private)
	/// help class for FilterKuwaharaNagaoGeneric
	/// replace sector with lowest variance by mean of h,s,v
	template <class ImageType, class AccessRGB>
	class FilterKuwaharaNagaoReplacePixelMeanHSV
	{
		public:
		void Replace(ImageType &Input, ImageType &Output, int x, int y, const tools::CROI &ROI, float mr, float mg, float mb)
		{
			int Ms = 0, Mv = 0, 
				Mhd = 0; // sum of offsets to angle 0  
			// calculate mean color of best sector in hsv color space
			unsigned char r,g,b;
			int RedLowCount = 0,
				RedHighCount = 0,
				HueCount = 0;
			short	int h;
					unsigned char s,v;
			for (unsigned int ry = y+ROI.y1(); ry <= y+ROI.y2(); ++ry)
			{
				for (unsigned int rx = x+ROI.x1(); rx <= x+ROI.x2(); ++rx)
				{
					r = AccessRGB::GetR(Input(rx,ry));
					g = AccessRGB::GetG(Input(rx,ry));
					b = AccessRGB::GetB(Input(rx,ry));
					tools::RGB2HSVd(r,g,b,h,s,v); // 255,255,255,359,255,255
												  /*
												  Mhd += tools::CycleDiff(0, h, 360);
					*/
					if (h<=60) RedLowCount+=360;
					else if (h>=300) RedHighCount++;
					Mhd+=h;
					HueCount++;
					
					Ms += s;					
					Mv += v;
				}
			}
			Ms /= 4;
			Mv /= 4;
			if (HueCount>0) 
			{ // works, if colors not to far away from each other
				if (RedHighCount>0)
					Mhd = (Mhd + RedLowCount + (HueCount >> 1)) / HueCount;
				else 
					Mhd = (Mhd + (HueCount >> 1)) / HueCount;
				if (Mhd>=360) Mhd = Mhd - 360;
			}
			else Mhd = 0;
			//tools::HSV2RGBd(Mhd, Ms, Mv, r, g, b);
			tools::HSV2RGBd(h, s, v, r, g, b);
			// replace color by mean of h,s,v
			Output(x,y)	= AccessRGB::PackRGB(r, g, b);			
		}
	};

	/// \author Dirk Balthasar (private)
	/// \author Dirk Balthasar (private)
	/// help class for FilterKuwaharaNagaoGeneric
	/// replace sector with pixel with lowest distance to r,g,b mean value
	template <class ImageType, class AccessRGB>
	class FilterKuwaharaNagaoReplacePixelMeanMinDist
	{
		public:
		void Replace(ImageType &Input, ImageType &Output, int x, int y, const tools::CROI &ROI, float mr, float mg, float mb)
		{
			unsigned char
				mri = (unsigned char)mr,
				mgi = (unsigned char)mg,
				mbi = (unsigned char)mb,
				bestr,bestg,bestb;
			float MinMeanDist = -1;
			for (unsigned int ry = y+ROI.y1(); ry <= y+ROI.y2(); ++ry)
			{
				for (unsigned int rx = x+ROI.x1(); rx <= x+ROI.x2(); ++rx)
				{
					unsigned char	
						r = AccessRGB::GetR(Input(rx,ry)),
						g = AccessRGB::GetG(Input(rx,ry)),
						b = AccessRGB::GetB(Input(rx,ry));
					float d = tools::DistRGBEuklidPow2(r, g, b, mri, mgi, mbi);
					if (MinMeanDist < 0)
					{ // first pixel
						MinMeanDist = d;
						bestr = r;
						bestg = g;
						bestb = b;
					}else
					{
						if (d < MinMeanDist)
						{
							MinMeanDist = d;
							bestr = r;
							bestg = g;
							bestb = b;
						}
					}
				}
			}
			Output(x,y)	= AccessRGB::PackRGB(bestr,bestg,bestb);			
		}
	};

	/// \author Dirk Balthasar (private)
	/// \author Dirk Balthasar (private)
	/// help class for FilterKuwaharaNagaoGeneric
	/// replace sector with pixel with lowest distance to r,g,b mean value if center pixel has max distance to mean
	template <class ImageType, class AccessRGB>
	class FilterKuwaharaNagaoReplaceMeanMinIfMax
	{
		public:
		void Replace(ImageType &Input, ImageType &Output, int x, int y, const tools::CROI &ROI, float mr, float mg, float mb)
		{
			unsigned char
				mri = (unsigned char)mr,
				mgi = (unsigned char)mg,
				mbi = (unsigned char)mb,
				bestr,bestg,bestb;
			float MinMeanDist = -1, MaxMeanDist = -1;
			int MaxMeanDistX, MaxMeanDistY;
			for (unsigned int ry = y+ROI.y1(); ry <= y+ROI.y2(); ++ry)
			{
				for (unsigned int rx = x+ROI.x1(); rx <= x+ROI.x2(); ++rx)
				{
					unsigned char	
						r = AccessRGB::GetR(Input(rx,ry)),
						g = AccessRGB::GetG(Input(rx,ry)),
						b = AccessRGB::GetB(Input(rx,ry));
					float d = tools::DistRGBEuklidPow2(r, g, b, mri, mgi, mbi);
					if (MinMeanDist < 0)
					{ // first pixel
						MaxMeanDist = d;
						MaxMeanDistX = rx;
						MaxMeanDistY = ry;
						MinMeanDist = d;
						bestr = r;
						bestg = g;
						bestb = b;
					}else
					{
						if (d > MaxMeanDist)
						{
							MaxMeanDist = d;
							MaxMeanDistX = rx;
							MaxMeanDistY = ry;
						}
						if (d < MinMeanDist)
						{
							MinMeanDist = d;
							bestr = r;
							bestg = g;
							bestb = b;
						}
					}
				}
			}
			if (MaxMeanDistX == x && MaxMeanDistY == y)
			{ // replace if center pixe has maximum distance to mean
				Output(x,y)	= AccessRGB::PackRGB(bestr,bestg,bestb);			
			}else
			{ // center pixel is ok
				Output(x,y)	= Input(x,y);
			}
		}
	};


	/// \author Dirk Balthasar (private)
	/// Kuwahara Nagao Filter core 
	/// replace sector with lowest variance by value calucalted with plugin
	/// \param PixelReplacer nessecary because of a compiler bug with templates in vcpp 6.0
	template <class ImageType, class AccessRGB, class FilterKuwaharaNagaoReplacePixel>
	void FilterKuwaharaNagaoGenericCore(ImageType &Input, ImageType &Output, FilterKuwaharaNagaoReplacePixel &PixelReplacer, std::vector<tools::CROI> &coord, const CROI &ROI)
	{
		int w = Input.GetWidth(), 
			h = Input.GetHeight();
		
		if (Output.GetWidth() != w || Output.GetHeight() != h)
			Output.SetSize(w,h);
		
		int sectors = coord.size();
		float varr, varg, varb;
		std::vector<float> varrgb, mr, mg, mb;
		varrgb.resize(sectors);
		mr.resize(sectors);
		mg.resize(sectors);
		mb.resize(sectors);
		for (unsigned int y = ROI.y1(); y <= ROI.y2(); ++y)
		{
			for (unsigned int x = ROI.x1(); x <= ROI.x2(); ++x)
			{
				// calculate variance of all sectors
				for (char s = 0; s < sectors; ++s)
				{
					tools::Variance<ImageType, AccessRGB>(Input, tools::CROI(x+coord[s].x1(), y+coord[s].y1(), x+coord[s].x2(), y+coord[s].y2()), varr, varg, varb, mr[s], mg[s], mb[s]);
					varrgb[s] = varr + varg + varb;
				}
				
				// find sector with lowest variance
				char mVar = 0;
				for (char i = 1; i < sectors; i++) if (varrgb[i] < varrgb[mVar]) mVar = i;
				// replace color by using plugin
				PixelReplacer.Replace(Input, Output, x, y, coord[mVar], mr[mVar], mg[mVar], mb[mVar]);
			}
		}
		
	}


	/// \author Dirk Balthasar (private)
	/// Kuwahara Nagao Filter with generic core plugins
	/// replace sector with lowest variance by value calucalted with plugin
	/// \param PixelReplacer nessecary because of a compiler bug with templates in vcpp 6.0
	template <class ImageType, class AccessRGB, class FilterKuwaharaNagaoReplacePixel>
	void FilterKuwaharaNagaoGeneric(ImageType &Input, ImageType &Output, FilterKuwaharaNagaoReplacePixel &PixelReplacer)
	{
		int w = Input.GetWidth(), 
			h = Input.GetHeight();
		if (Output.GetWidth() != w || Output.GetHeight() != h) Output.SetSize(w,h);
		std::vector<tools::CROI> coord;
		// core pixels
		coord.resize(4);
		coord[0] = tools::CROI(-1, -1,  0,  0);// upper left sector
		coord[1] = tools::CROI( 0, -1, +1,  0);// upper right sector
		coord[2] = tools::CROI( 0,  0, +1, +1);// lower right sector
		coord[3] = tools::CROI(-1,  0,  0, +1);// lower left sector
		FilterKuwaharaNagaoGenericCore<ImageType, AccessRGB, FilterKuwaharaNagaoReplacePixel>(Input, Output, PixelReplacer, coord, tools::CROI(1, 1, w-2, h-2));
		coord.resize(2);
		// left border
		coord[0] = tools::CROI( 0, -1, +1,  0);// upper right sector
		coord[1] = tools::CROI( 0,  0, +1, +1);// lower right sector
		FilterKuwaharaNagaoGenericCore<ImageType, AccessRGB, FilterKuwaharaNagaoReplacePixel>(Input, Output, PixelReplacer, coord, tools::CROI(0, 1, 0, h-2));
		// right border
		coord[0] = tools::CROI(-1, -1,  0,  0);// upper left sector
		coord[1] = tools::CROI(-1,  0,  0, +1);// lower left sector
		FilterKuwaharaNagaoGenericCore<ImageType, AccessRGB, FilterKuwaharaNagaoReplacePixel>(Input, Output, PixelReplacer, coord, tools::CROI(w-1, 1, w-1, h-2));
		// upper border
		coord[0] = tools::CROI( 0,  0, +1, +1);// lower right sector
		coord[1] = tools::CROI(-1,  0,  0, +1);// lower left sector
		FilterKuwaharaNagaoGenericCore<ImageType, AccessRGB, FilterKuwaharaNagaoReplacePixel>(Input, Output, PixelReplacer, coord, tools::CROI(1, 0, w-2, 0));
		// lower border
		coord[0] = tools::CROI(-1, -1,  0,  0);// upper left sector
		coord[1] = tools::CROI( 0, -1, +1,  0);// upper right sector
		FilterKuwaharaNagaoGenericCore<ImageType, AccessRGB, FilterKuwaharaNagaoReplacePixel>(Input, Output, PixelReplacer, coord, tools::CROI(1, h-1, w-2, h-1));
		coord.resize(1);
		// upper left corner
		coord[0] = tools::CROI( 0,  0, +1, +1);// lower right sector
		FilterKuwaharaNagaoGenericCore<ImageType, AccessRGB, FilterKuwaharaNagaoReplacePixel>(Input, Output, PixelReplacer, coord, tools::CROI(0, 0, 0, 0));
		// upper right corner
		coord[0] = tools::CROI(-1,  0,  0, +1);// lower left sector
		FilterKuwaharaNagaoGenericCore<ImageType, AccessRGB, FilterKuwaharaNagaoReplacePixel>(Input, Output, PixelReplacer, coord, tools::CROI(w-1, 0, w-1, 0));
		// lower left border
		coord[0] = tools::CROI( 0, -1, +1,  0);// upper right sector
		FilterKuwaharaNagaoGenericCore<ImageType, AccessRGB, FilterKuwaharaNagaoReplacePixel>(Input, Output, PixelReplacer, coord, tools::CROI(0, h-1, 0, h-1));
		// lower right border
		coord[0] = tools::CROI(-1, -1,  0,  0);// upper left sector
		FilterKuwaharaNagaoGenericCore<ImageType, AccessRGB, FilterKuwaharaNagaoReplacePixel>(Input, Output, PixelReplacer, coord, tools::CROI(w-1, h-1, w-1, h-1));
	}

	/// Symmetric nearest neighbour, help function
	/// \author Dirk Balthasar
	template <class ImageType, class AccessRGB>
		void FilterSNNcore(ImageType &Input, ImageType &Output, const tools::CROI &ROI, std::vector<tools::CROI>& coord)
	{

		int sz = coord.size();
		for (unsigned int y = ROI.y1(); y < ROI.y2(); ++y)
		{
			for (unsigned int x = ROI.x1(); x < ROI.x2(); ++x)
			{
				int mr = 0, mg = 0, mb = 0;
				for (char a = 0; a < sz; ++a)
				{
					unsigned char   
						cr = AccessRGB::GetR(Input(x,y)),
						cg = AccessRGB::GetG(Input(x,y)),
						cb = AccessRGB::GetB(Input(x,y)),
						r1 = AccessRGB::GetR(Input(x+coord[a].x1(),y+coord[a].y1())),
						g1 = AccessRGB::GetG(Input(x+coord[a].x1(),y+coord[a].y1())),
						b1 = AccessRGB::GetB(Input(x+coord[a].x1(),y+coord[a].y1())),
						r2 = AccessRGB::GetR(Input(x+coord[a].x2(),y+coord[a].y2())),
						g2 = AccessRGB::GetG(Input(x+coord[a].x2(),y+coord[a].y2())),
						b2 = AccessRGB::GetB(Input(x+coord[a].x2(),y+coord[a].y2()));
					if (tools::DistRGBEuklidPow2(cr, cg, cb, r1, g1, b1) < tools::DistRGBEuklidPow2(cr, cg, cb, r2, g2, b2))
					{ // 1
						mr += r1;
						mg += g1;
						mb += b1;
					}else
					{ // 2
						mr += r2;
						mg += g2;
						mb += b2;
					}
				}
				// replace color by mean of r, g, b
				Output(x,y)	= AccessRGB::PackRGB(mr/4, mg/4, mb/4);
			}
		}
	}

	/// Filter Symmetric nearest neighbour
	/// \author Dirk Balthasar
	template <class ImageType, class AccessRGB>
		void FilterSNN(ImageType &Input, ImageType &Output)
	{
		int w = Input.GetWidth(), 
			h = Input.GetHeight();
		
		if (Output.GetWidth() != w || Output.GetHeight() != h)
			Output.SetSize(w,h);
		
		std::vector<tools::CROI> coord;

		// core of image
		coord.resize(4);
		coord[0] = tools::CROI(-1, -1, +1, +1);
		coord[1] = tools::CROI( 0, -1,  0, +1);
		coord[2] = tools::CROI(+1, -1, -1, +1);
		coord[3] = tools::CROI(-1,  0, +1,  0);
		FilterSNNcore<ImageType, AccessRGB>(Input, Output, tools::CROI(1, 1, w-1, h-1), coord);
		// corner dots (just clone)
		for (int y = 0; y < h; y++)
		{
			Output(0,y) = Input(0,y);
			Output(w-1,y) = Input(w-1,y);
		}
		for (int x = 0; x < w; x++)
		{
			Output(x,0) = Input(x,0);
			Output(x,h-1) = Input(x,h-1);
		}
	}
	
};

#endif

⌨️ 快捷键说明

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