2017-01-11 21:41:22 sinat_27614619 阅读数 1049
传统的编程思路都是面向过程的,C++则是面向对象的编程,那么我们设计程序时应该充分使用C++封装的思想,把图像处理抽象成类。这样便于代码的维护和移植。
本篇的例子是构建一个简单算法,鉴别出图像中含有给定颜色的所有像素。该算法输入的是图像及颜色,并返回表示含有指定颜色的像素的二值图像。该算法还需要指定另一个参数,即对颜色偏差的容忍度。
但由于RGB颜色空间计算颜色之间的距离并不是衡量颜色相似度最好的方法,事实上,RGB并不是一个感知上均匀分布的色彩空间。为了解决这个问题,人们提出了感知上均匀分布的色彩空间,CIEL*a*b就是这样一个颜色空间。opencv函数cv::cvtColor可以轻易的在不同颜色空间进行转换。
下面贴代码:

ColorDetector.h

#pragma once
#include<opencv2\opencv.hpp>
#include<iostream>
class ColorDetector
{
private:
       cv::Mat m_converted;//转换颜色空间的图片
       int m_threshod;//容忍度偏差
       cv::Vec3b m_model;//要查找的颜色
public:
       cv::Mat m_result;//最终得到的二值图像
       ColorDetector();
       ~ColorDetector();
       void setModel(cv::Vec3b &target);//设置要查找的颜色
       
       void setModel(uchar red, uchar green, uchar blue);//设置查找颜色的接口,这种颜色值设置在RGB通道上
       
       void setModel2(uchar red, uchar green, uchar blue);//设置查找颜色的接口,这种颜色值转换到LAB颜色空间上
       
       void setThreshold(int distance);//设置容忍度的接口
       
       int getDistance(cv::Vec3b &pixls);//解算图像像素点与要查找的颜色的距离
       
       cv::Mat process(const cv::Mat &image);
       cv::Mat process2(const cv::Mat &image);
};
ColorDetector.cpp
#include "ColorDetector.h"
//构造函数,给成员变量初始化,容忍度偏差设为100,查找的三通道颜色默认设为0
ColorDetector::ColorDetector():m_threshod(100)
{
       m_model[0] = m_model[1] = m_model[2] = 0;
}
ColorDetector::~ColorDetector()
{
}
void ColorDetector::setModel(cv::Vec3b & target)
{
       m_model = target;//cv::Vec3b类型,三通道
}
void ColorDetector::setModel(uchar red, uchar green, uchar blue)
{
       m_model[0] = blue;
       m_model[1] = green;
       m_model[2] = red;
}
void ColorDetector::setModel2(uchar red, uchar green, uchar blue)
{
       cv::Mat tmp(1, 1, CV_8UC3);//定义一个三通道的像素点
       tmp.at<cv::Vec3b>(0, 0)[0] = blue;
       tmp.at<cv::Vec3b>(0, 0)[1] = green;
       tmp.at<cv::Vec3b>(0, 0)[2] = red;
       cv::cvtColor(tmp, tmp, CV_BGR2Lab);//颜色空间转换,把RGB——>Lab
       m_model = tmp.at<cv::Vec3b>(0, 0);
}
void ColorDetector::setThreshold(int distance)
{
       m_threshod = distance;//设置容忍度
}
//这里的距离公式采用1范数
int ColorDetector::getDistance(cv::Vec3b & pixls)
{
       return abs(pixls[0] - m_model[0])
              + abs(pixls[1] - m_model[1])
              + abs(pixls[2] - m_model[2]);
}
cv::Mat ColorDetector::process(const cv::Mat & image)
{
       m_result.create(image.size(), CV_8U);
       cv::Mat_<cv::Vec3b>::const_iterator it = image.begin<cv::Vec3b>();
       cv::Mat_<cv::Vec3b>::const_iterator itend = image.end<cv::Vec3b>();
       cv::Mat_<uchar>::iterator out = m_result.begin<uchar>();
       while (it != itend)
       {
              //循环遍历,把查找到的颜色转换为二值图像,这里按照RGB空间的颜色距离解算
              if (getDistance(*it) < m_threshod)
                     *out = 255;
              else
                     *out = 0;
              ++it;
              ++out;
       }
       return m_result;
}
cv::Mat ColorDetector::process2(const cv::Mat & image)
{
       m_result.create(image.size(), CV_8U);
       m_converted.create(image.size(), image.type());
       //把输入图像从RGB颜色空间转换到Lab颜色空间
       cv::cvtColor(image, m_converted, CV_BGR2Lab);
       cv::Mat_<cv::Vec3b>::const_iterator it = m_converted.begin<cv::Vec3b>();
       cv::Mat_<cv::Vec3b>::const_iterator itend = m_converted.end<cv::Vec3b>();
       cv::Mat_<uchar>::iterator out = m_result.begin<uchar>();
       while (it != itend)
       {
              if (getDistance(*it) < m_threshod)
                     *out = 255;
              else
                     *out = 0;
              ++it;
              ++out;
       }
       return m_result;
}

main.cpp
#include"ColorDetector.h"
int main()
{
       
       cv::Mat image = cv::imread("boldt.jpg");
       ColorDetector detector;//构造类
       
       detector.setModel(130, 190, 230);//查找蓝天的颜色
       cv::namedWindow("Process");
       cv::imshow("Process", detector.process(image));
       detector.setModel2(130, 190, 230);//查找蓝天的颜色
       cv::namedWindow("Process2");
       cv::imshow("Process2", detector.process2(image));
       
       cv::waitKey(0);
       return 0;
}
运行结果:

参考原图:

2014-01-13 21:50:00 xj2419174554 阅读数 5695

原创作品,出自 “晓风残月xj” 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj)。

由于各种原因,可能存在诸多不足,欢迎斧正!

1.课程论文题目

去雾。

本次论文我的选题是去雾。由于对《图像处理与分析》这门课很感兴趣,同时也为了锻炼一下自己学习新知识的能力,我没有选择一些容易的常规的图像处理与分析算法,而是选择较为前沿的去雾算法。作为一名计算机专业的学生,我认为仅仅掌握基本的程序设计思想与常规算法是远远不够的,还要培养自己不断学习的能力—学习新知识、学习新思想的能力。这方面很重要的体现就是了解相关科技前沿,尽自己最大努力研读新论文。此外,我认为一个好的课程报告应该有一定的实用价值,或者说写报告的人应该尽可能使自己的选题有实用价值。众所周知,伴随着我国经济的快速发展,一些一味追求GDP的粗制乱造的发展模式所带来的严重后果正在干扰着我们的正常生活方式。我这次报告所要探讨的主题—雾就是其中不可忽视的因素。我这里所说的雾,是广义的雾,包括雾、霾、沙尘、烟等一切导致视觉效果受限的物理现象。由于雾的存在,户外图像质量降低,如果不处理,往往满足不了相关研究、应用的的要求。在雾的影响下,经过物体表面的光被大气中的颗粒物吸收和反射,导致获取的图像质量差,细节模糊、色彩暗淡。通过一定的技术手段,去掉物体表面的雾霭,增强图片效果显得尤为重要。

2.程序设计思路

由于我的程序可处理的图片可以是灰度的、彩色的两种。所以我设计了两种算法实现不同格式图片的处理:直方图灰度分布均衡化去雾算法,基于单幅图像的快速去雾算法。

 

1)、直方图灰度分布均衡化去雾算法

在此我先谈谈我对直方图均衡化的认识。

直方图均衡化(英文名Histogram Equalization),通过使用累积函数对灰度值进行“调整”以实现对比度的增强。具体说来,即把原图像对应的灰度直方图从比较集中的灰度区间通过一定的转换变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。

直方图均衡化的具体编程实现为

    A.统计每个灰度等级对应的像素点数 

    B.计算累计概率

    C.重新映射图像像素点灰度

在这里我首先统计0-255个灰度等级i的像素点数Color[i],然后分别除以图像总的像素点求出每个灰度等级对应的概率PerProbability[i];接着运用积分的思想来计算累计概率AccuProbability[i];然后映射求得新的像素值NewColor[i]

 

 上述坐标图和积分式解释了积分思想求累计概率的正确性。下面举个例子展示整个过程。

a.假设下面使是图像对应的像素点:

 

b.下面是中间处理工程

 

c.经过处理后图像对应的像素点:

 

为什么直方图灰度分布均衡化可以在一定成都上达到去雾的效果呢?这是因为通过使用累积函数对灰度值进行“调整”以实现对比度的增强,一定程度上使暗的地方更暗、亮的地方更亮,从而在视觉上达到去雾的效果。

但是上面的去雾效果仅仅局限于灰度图片,而不能处理更为实用的彩色图像。经过上述直方图处理后,达到均衡化图像的目的,但是图像会在原图基础上失真或称为走样,即整幅图像的颜色发生很大改变,严重偏离去雾的初衷(去雾是在原图基础上除去表面的薄纱从而增强整幅图像的视觉效果)。

 综上,直方图灰度分布均衡化去雾算法可以处理灰色图,但对于彩色图像就会出现走样,达不到去雾的效果。为了解决彩色图像的去雾问题,我又看了一些最新论文,其中包括何凯明博士的《Single Image Haze Removal Using Dark Channel Prior》论文,这是一篇非常深刻的文章,里面公式推导很多,我硬着头皮读完后看不懂,于是又到博客园、CSDN上筛选出几篇相对容易理解和实现的论文,其中我对清华大牛刘倩、陈茂银、周东华的《基于单幅图像的快速去雾算法》论文非常感兴趣,决定以其为突破点尝试彩色图像的去雾算法实现。

 

 

2.基于单幅图像的快速去雾算法

由于基于单幅图像的快速去雾算法涉及的学科非常多、理论性非常强,在此我的设计思路主要是取自清华大牛刘倩、陈茂银、周东华的《基于单幅图像的快速去雾算法》论文以及在编写程序的过程中在一定程度上参考了CSDN博客兰专家laviewpbt博客《一种可实时处理 O(1)复杂度图像去雾算法的实现》,由于所处理图片的格式不同,以及论文、博客里都没提供源码,所以在编写程序的过程中我并无抄袭。在读论文的过程中,真的是充满了对论文撰写者的佩服之情。之前徐老师在课堂上介绍说《图像处理与分析》是门交叉学科,博大精深,那时还愚昧的不以为然,一则是因为所学知识太少,眼界受限,没有了解相关的前言领域;二来是课下编程不够,虽说自己实现了图像几何变换、图像增强等算法,但总的难度很低,而且刚开始接触时不会还能参照先驱的程序。在看了几篇图像处理的前研论文之后,我感觉到自己的愚昧无知。下面就谈谈对我《基于单幅图像的快速去雾算法》论文的一些理解。

在计算机视觉领域,通常运用严密的数学物理方法来描述雾霾等自然现象,《基于单幅图像的快速去雾算法》论文中提出算法的出发点就是基于衰减模型和环境光模型的,并且提出了一个模型表达式:

 

x为空间坐标,F是待恢复的无雾图像,r是大气散射系数,d是景物深度,A是与x无关的全局大气光,H为有雾情况下的景物图像。

这是基于大气理论的光学表达式,由于知识有限,我只能照搬了。

 

      上面是程序的算法流程,下面我将依次谈谈我对每个步骤的理解。

Step 1  读入待处理的图像

论文以及其他关于去雾的程序都是基于较高格式的图像的,普通bmp尤其是268色位图的处理没有涉及,这也是我选择去雾算法实现的一个重要原因—不简单机械地重复别人做过的东西。

 

 Step 2 求空间最小颜色通道

基本色通道(color channel),就是将构成整体图像的颜色信息整理并表现为单色图像的工具。我们知道现实世界中的颜色都是由红、绿、蓝3中颜色组成的。本步骤是要求出所有空间坐标位置对应的最小颜色通道,即Ri,Gi,Bi中最小者,得到新图像M

 

 Step 3 M进行均值滤波

     均值滤波是徐老师在课堂上重点讲过的。均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素,再用模板中的全体像素的平均值来代替原来像素值。 可见均值滤波的关键是选择模板,然后对应相乘相加相除,这个过程是比较简单。

 

Step 4 M所有像素点求均值Mav

直接把M中的下所有像素相加然后除以总像素数即可。

 

Step 5  求环境光估计值

去雾很大程度上就是要考虑环境光的影响,还远物体的庐山真面目。利用均值滤波求出的环境光具有深度缓变处平滑,深度跳变处随之跳变变的特点。当M的深度发生较大变化时M,Mav也随之发生较大变化,最终体现在L上。

 

Step 6 求出全局大气光

全局大气光也是对图像的重要影响因素。通常取最大灰度值为全局大气光A

 

Step 7 还原图像

     考虑环境光、全局大气光的影响,利用算法开头给出的模型表达式还原图片。

 

   上面就是整个过程。在原论文中,上述都给出较为严格的证明,由于相关专业知识有限,我就不交代推理证明过程了。

    

   

3.数据结构与算法设计

1)、直方图灰度分布均衡化去雾算法

     由于整个处理过程中没有特殊要求的操作,所以开辟二维数组就可解决问题。分别开辟3个二维数组

int *Color=new int[MAXNCOLOR];//Color[i]存储该灰度等级i对应的像素点数,同时为了节省内存空间,在映射后Color[i]则存储原来灰度等级i对应的新灰度等级,这样做可以少申请一个二维数组,由于图像处理很占内存空间,因此优化是必须的。

double *PerProbability=new double[MAXNCOLOR];//存储灰度等级i对应的概率PerProbability[i].

double* AccuProbability=new double[MAXNCOLOR];//存储灰度等级i对应的累加概率AccuProbability[i],此数组可以和上面的PerProbability[]数组合成一个,为了程序的可读性,我开了两个数组,但须明确此处可以优化。

 

此算法原理理解起来可能不是很容易,但实现起来却很简单,无需特殊编程技巧,在此就不给出伪代码,只给出大致流程:统计每个灰度等级对应的像素点数 ,计算累计概率,重新映射屏幕像素点灰度,具体实现见第4部分直方图灰度分布均衡化去雾算法源代码。此算法时间复杂度为O(n),空间复杂度为O(n),n为空间像素点数。

 

2.基于单幅图像的快速去雾算法

     上面的空间最小颜色通道和均值Mav可以在求所有点的颜色通道是一起求出,不必另写循环语句比较求得。由于编程实现较简单,在此就不多说了。

    具体算法步骤见程序设计思路部分,具体源代码见第4部分基于单幅图像的快速去雾算法。

 

4.程序关键代码

、直方图灰度分布均衡化去雾算法源代码
/*************************************************
*功能:直方图灰度分布均衡化去雾算法
**************************************************/
void CMyDIPView::OnMenuitem32790() 
{
	const int MAXNCOLOR=256+10;
	unsigned char *lpSrc;
	CMyDIPDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if(pDoc->m_hDIB == NULL)
		return ;
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->m_hDIB);
	LPSTR lpDIBBits=::FindDIBBits (lpDIB);
	int cxDIB = (int) ::DIBWidth(lpDIB);
	int cyDIB = (int) ::DIBHeight(lpDIB);
	int *Color=new int[MAXNCOLOR];
	memset(Color,0,sizeof(Color));
	long lLineBytes = WIDTHBYTES(cxDIB * 8);

	//统计每个灰度等级对应的像素点数
	for(int i = 0; i < cyDIB; i++)
	{
		for(int j = 0; j < cxDIB; j++)
		{
			Color[*(lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j)]++;
		}
	}	

	//计算每个灰度等级对应的概率
	double *PerProbability=new double[MAXNCOLOR];
	double TotalPixelNumber=cxDIB*cyDIB*1.0;
	for(i=0;i<256;i++)
	{
		PerProbability[i]=Color[i]*1.0/TotalPixelNumber;
	}
    //计算每个灰度等级对应的累加概率
	double* AccuProbability=new double[MAXNCOLOR];
	AccuProbability[0]=PerProbability[0];
	Color[0]=(int)(AccuProbability[0]*255.0f+0.5f);
	for(i=1;i<256;i++)
	{
		AccuProbability[i]=AccuProbability[i-1]+PerProbability[i];
		Color[i]=(int)(AccuProbability[i]*255.0f);
	}
	
	//重新映射屏幕像素点灰度
	for(i = 0; i < cyDIB; i++)
	{
		for(int j = 0; j < cxDIB; j++)
		{
			unsigned char perpixel=*(lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j);
			*(lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j)=Color[perpixel];
			
		}
	}
	::GlobalUnlock((HGLOBAL) pDoc->m_hDIB);
	Invalidate(TRUE);
}



.基于单幅图像的快速去雾算法
/*************************************************
*功能:基于单幅图像的快速去雾算法
**************************************************/
void CMyDIPView::OnMenuitem32791() 
{
	unsigned char *lpSrc;
	CMyDIPDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if(pDoc->m_hDIB == NULL)
		return ;
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->m_hDIB);
	LPSTR lpDIBBits=::FindDIBBits (lpDIB);
	int cxDIB = (int) ::DIBWidth(lpDIB); 
	int cyDIB = (int) ::DIBHeight(lpDIB);  
	long lLineBytes = WIDTHBYTES(cxDIB * 8); 
	double sumMinColor=0;//所有颜色通道的累加和
	double aveMinColor=0;//所有颜色通道的平均值
	unsigned char minColor;//颜色通道最小值
	unsigned char maxColor=0;//所有颜色通道最大值
	int maxFlag=0;//标记颜色通道最大值权重
	int minFlag=0;//标记颜色通道最小值权重
	unsigned char *mNewPicture=new unsigned char[cxDIB*cyDIB];
	for(int i = 0; i < cyDIB; i++)
	{
		for(int j = 0; j < cxDIB; j++)
		{
			
			unsigned char perpixel=*(lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j);
			unsigned char red=perpixel/32;
			minFlag=32;
            minColor=red;
			if(maxColor<red)
			{
				maxColor=red;
				maxFlag=32;
			}
			perpixel%=32;
			unsigned char green=perpixel/8;
			if(minColor>green)
			{
				minColor=green;	
				minFlag=8;
			}
			if(maxColor<green)
			{
				maxColor=green;
				maxFlag=8;
			}
			
			unsigned char blue=perpixel%8;
			if(minColor>blue)
			{
				minFlag=1;
				minColor=blue;
			}
			if(maxColor<blue)
			{
				maxColor=blue;
				maxFlag=1;
			}
			mNewPicture[cxDIB * (cyDIB - 1 - i) + j]=minColor*minFlag;
			sumMinColor+=minColor*minFlag;
		}
	}
	aveMinColor=sumMinColor/(cxDIB*cyDIB);//颜色通道平均值
	maxColor*=maxFlag;
	double maxAveColor=0;//均值滤波后颜色通道平均值
	double *mAveNewPicture=new double[cxDIB*cyDIB];
	double xishu=1.0/100.0;
	int h=cyDIB,w=cxDIB;
	int tem_w=10,tem_h=10;
	int dw = cxDIB;
	double sum;
    for(i=0;i<h;i++)
    {  
		for(int j=0;j<w;j++)
		{   	
			sum=0;	
			if( j<((tem_w-1)/2) || j>(w-(tem_w+1)/2) || i<((tem_h-1)/2) || i>(h-(tem_h+1)/2) )
				mAveNewPicture[i*dw+j]=mNewPicture[i*dw+j];
			else 
			{ 	
				for(int m=i-((tem_h-1)/2);m<=i+((tem_h-1)/2);m++)
				{
					for(int n=j-((tem_w-1)/2);n<=j+((tem_w-1)/2);n++)
					sum+=mNewPicture[m*dw+n];

				}	
				sum=sum*xishu;sum = fabs(sum);	
				if(sum<0)     sum=0;	
				if(sum>255)sum=255;
				mAveNewPicture[i*dw+j]=sum;
			}
			if(maxAveColor<mAveNewPicture[i*dw+j])
				maxAveColor=mAveNewPicture[i*dw+j];
		}
	} 
	double *lNewPicture=new double[cxDIB*cyDIB];
	for(i = 0; i < cyDIB; i++)
	{
		for(int j = 0; j < cxDIB; j++)
		{
          lNewPicture[i*cxDIB+j]=min(min(aveMinColor*1.28,0.9)*mAveNewPicture[i*cxDIB+j],mNewPicture[i*cxDIB+j]);
		}
	}
	double A=(maxColor+maxAveColor)/2.0;
	for(i = 0; i < cyDIB; i++)
	{
		for(int j = 0; j < cxDIB; j++)
		{
			double H=*(lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j);
	        double L=lNewPicture[cxDIB * (cyDIB - 1 - i) + j];
			*(lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j)=(H-L)/(1-L/A);
		}
	}
	::GlobalUnlock((HGLOBAL) pDoc->m_hDIB);
	Invalidate(TRUE);
}


 

 5.程序运行结果

(2)、直方图灰度分布均衡化去雾算法

图像1

  去雾前

 

 

图像2

   去雾前:

 


图像3

 

 

    对于上面3张灰度图像,直方图灰度分布均衡化达到的去雾效果是不错的,但是对于彩色图像,却无法回避走样问题。下面给出的就是直方图灰度分布均衡化在处理彩色图像时遇到的问题。

图像4

   去雾前

 

   图像4在直方图灰度分布均衡化后景物形状保持了,但色彩却严重偏离了,关于原因,上面已有解释。



(2).基于单幅图像的快速去雾算法

图像5

 

 

图像6

  去雾前

 

 

图像7

  去雾前

 

 

6.编程中遇到的困难及解决方法

1)、选题

    由于徐老师没有要求具体做什么,这个长期习惯老师出题然后自己动手编程的我带来一定干扰。自主选题也是一种自主学习能力,结合自己的兴趣与能力选择适合自己的选题。由于之前做ACM,我认为自己有一定的解决问题能力,于是选择了较为前沿的去雾算法。

  

(2)、查资料

由于本次我的选题较为前沿,所以相关资料不好找,有用的思想、算法等都得通过最近几年的论文获得。之前没有读过多少论文,尤其是像这次这样理论性很强的论文,所以在这方面遇到一定的麻烦。最后,通过CSDN和博客园两个平台,我找的了相关论文和可供参考的博客(在此对大牛们表示感谢)。

 

(3)、关于bmp格式的256色位图的处理

在我看到的相关论文里讨论的都是较高格式的图像,而徐老师给的程序框架是基于bmp格式的256色位图。我首先想到的是修改老师的程序,使之变成具有处理较高格式图片的能力,但由于时间以及没有牢固的MFC编程基础,最终没能动手改。但通过仔细阅读相关论文发现算法是可以处理bmp格式的256色位图的。

 

(4)、直方图灰度分布均衡化去雾算法处理彩色图

开始我打算直接用直方图灰度分布均衡化去雾算法处理彩色图片,但总是达不到预期的效果。图像上景物的轮廓是保持了,但颜色却发生很大的变化,没有达到去雾的效果。在多次修改程序不见改善的情况下我选择了重新看课本,经过一番理论分析,我搞清楚了直接直方图均衡化能增强整幅图像的效果,但不能使彩色图像的黯淡部分在不走样的情况下变亮。当然后来看到博客园上专家Imageshop的

 《限制对比度自适应直方图均衡化算法原理、实现及效果》以及

 《局部自适应自动色阶/对比度算法在图像增强上的应用》文章发现用人工智能中自适应方法也可以使直方图均衡化具备处理彩色图像的能力。但自适应的相关理论对刚开始接触图像处理的我来说有难度,所以我只用直方图均衡化处理灰度图像。

 

(5)、获取bmp格式的256色位图的颜色通道

基于单幅图像的快速去雾算法有一个很重要的一点就是获取原图像空间坐标像素点处的颜色通道中的最小者。关于获取颜色通道,在24位存储格式时可以通过依次访问3个字节获取相应的颜色通,也可以通过GetRValueGetRValueGetRValue等函数直接取出红绿蓝3种颜色通道,等等,但这些都不能处理8位的图像,后来我在CSDN上论坛上问别人,有人说RGB在一个字节中分别占3,2,3个比特位,于是我选用想到位操作或求模两种方法。

 

(6)、均值滤波模板大小的设置

     关于这点,徐老师课堂上是可以结合实际情况自己设定。但当面对具体情况时,模板大小的设定很有技巧。均值滤波可以对图像进行模糊处理、平滑处理,在一定范围了随模板大小的增大而增大,当达到某个峰值之后随模板大小的增大而减小。上述是本次实验经验所得,可能不符合理论,但我的程序结果却支持这种结论。

 

(7)、ρ参数的大小设置

   ρ参数的大小控制了图像去雾能力的大小,越大,雾气越少,图像越显得暗,越小,图像偏白,雾气越浓。所以在合适的范围内参数ρ应该尽可能取得大点,实验中我去的是1.28

 

7.总结心得

     在本次写报告的过程中,我最大的感觉就是知识欠缺。在我目前接触的图像处理算法中,没有特别难编程实现的,大多可以通过基本的编程方法解决。但是,其中的指导思想却是很需要用心体会的。在编程时一定要上升到理论层次,多问几个为什么:为什么这么做,为什么会有这样的效果等等。

    在我看来,图像处理就是一个矩阵变换,变换的是矩阵中对应空间坐标的像素值。而变换过程中要用到很多模板、算子、算法等,这些是进行矩阵变换的依据。在理论工作完成以后,再进行动手编程,这样才能达到真正学习图像处理与分析的目的。有的理论看起来很简单,但却温含着丰富的专业知识,需要我们静下心来慢慢体会,仔细琢磨;有的理论看起来就很难,就像我选的《基于单幅图像的快速去雾算法》这篇论文,从头到尾都体现着丰富的专业知识、严密的逻辑推理能力与深厚的科学内涵,对于这样的理论,更是难得的思想启蒙,我们应该迎难而上,尽可能的读懂它。当然在编程的过程中,我们也要不断优化自己的程序,图像对象的数据量很大,稍不留神算法的时间或空间复杂度就会很高,即便常数级的优化也是很有必要的,能少开辟数组是就少开辟,能少用一层循环就少用一层循环。

有人的地方就会有审美需求,而图像处理就是一种美化过程。图像处理是指对图像信息进行加工,从而满足人类的心理、视觉或者应用需求的思想与技术。常用的图像处理方法有图像的采集与数字化、图像的编码、图像的增强、图像恢复、图像分割、图像分析等。在学习《图像处理与分析》课时要注重理论,多想想为什么;同时也应多动手,获得相应的编程体验。

 

 

 

8、参考文献

1.刘倩、陈茂银、周东华 《基于单幅图像的快速去雾算法》论文

 

2.CSDN博客兰专家laviewpbt博客《一种可实时处理 O(1)复杂度图像去雾算法的实现

 

3.何凯明 《Single Image Haze Removal Using Dark Channel Prior》论文

这是我图像处理与分析结课报告,参考了很多大牛的论文、博客,在此对他们表示感谢!文章和程序中可能有很多缺陷或错误,还请大牛斧正。


    如果觉得对你有所帮助,给几毛资助也是不错的想法!下面是博主的支付宝二维码,如果有一天收到你的资助,将无比欣慰!

                   

2015-05-09 18:18:20 luoweifu 阅读数 1128

《编程思想》

敬请期待……


《图像处理与搜索(java)》

创建时间:2014-07-19
文章数:18篇
随着计算机和信息技术的发展,图像处理和搜索技术越来越受到重视,也有越来越广泛的应用。本专栏是我大三做一个关于图像搜索技术的项目时积累的技术。从最基础的数字图像基础开始讲起,每一章都结合Java代码具体实现。
文章地址:图像处理与搜索(java)


《算法程序设计》

创建时间:2014-01-25
文章数:11篇
本人对数据结构、算法比较感兴趣。从《挑战程序设计(竞赛)》一书中收获颇多!本专栏就是记录我在学习该书时的笔记和所得到的感悟,希望对大家有所帮助,我结合自己的实践分别用C++和Java两种语言进行了实现,两种语言各有各的优点,读者自己去本会吧!
文章地址:算法程序设计


《java伴我一路走来》

创建时间:2013-09-11
文章数:22篇
从大一下学期,就开始学习java;从大二上学期,就开始写博客;java——伴随我一路走来到现在!java,可以说是一门博大精深的语言,从基础语法到面向对象的概念,再到java高级编程,再到java EE企业,亦或是到移动平台的android,学不完,用不尽!
文章地址:java伴我一路走来


《数据结构(java)》

创建时间:2013-01-16
文章数:16篇
数据结构对于一个程序员来说是必备的基础。这是我在大二时用java实现的基本数据结构,现在对它加以一些修改和完善后贴到网上来。对大鸟来说,这些都是烂熟于心了;但对于小菜来说,也许还有一些参考价值!
文章地址:数据结构(java)


2014-07-29 18:45:23 iloveas2014 阅读数 605

总目录:http://blog.csdn.net/iloveas2014/article/details/38304477

内容编排

        本套教程共分3部分。

        第一部分介绍色彩的相关知识及Flash,Photoshop等可视化软件在图形图像处理方面的一些特性,包括常用的色彩模式,Photoshop图层效果,ActionScript滤镜,混合模式等知识,并指出这些特性在不同软件下的异同。

        第二部分以应用数学为思想,以BitmapData,像素为工具,深入剖析各种图像处理技术的工作原理,让读者可以深入到算法的层面上认识图像处理,在ActionScript乃至其它支持像素级编程的语言中实现与Photoshop等专业图像软件相媲美的图形效果。

        第三部分将充分发挥程序在交互、随机等方面的优势,运用以上学过的知识制作各种有趣的应用,游戏或者交互动画效果,让您的程序作品以艺术的形式走进千家万户,感染着与您互动的每一位观众。

2018-05-27 22:38:12 FPGAerClub 阅读数 3827

更多精彩内容,请微信搜索“FPGAer俱乐部”关注我们

基于软件的图像处理方法存在着一些局限性,尤其是计算速度和算法效率方面。所以大家很自然的就想到了FPGA作为嵌入式图像应用的平台。许多图像处理本身就是并行计算的,并且FPGA的编程硬件,本质上也是并行的。但是利用FPGA硬件进行图像处理存在很多的困难,需要学到很多的技巧。下面我介绍两几种比较基础的图像处理算法思想。

 

单幅图像的点操作是图像处理中最简单的操作,输出值只取决于输入值,与位置无关,可以看作是一个函数的映射。从硬件实现的角度来说,最简单的方式就是通过一个实现函数的模块对输入的每个像素进行依次处理,也就是流水化处理。每个像素都是单独处理的,可以把图像分为若干部分,每个部分单独处理,所以点操作容易并行实现。点操作可作为读取图像和后续处理之间的一个桥梁。A:亮度调节;为了使图像变亮,可以增大输出像素值,可以通过加一个常量实现。类似地,变暗减小像素值。但是实际中,调节亮度要复杂的多,因为人的视觉系统是非线性的。B:对比度调节;图像的对比度受映射函数的斜率影响。斜率大于1增强,小于1则降低,可以通过乘以一个大于或者小于1的常数实现。C:同时调节亮度和对比度;一个简单的调节它们的点操作是:Q=aI+b=a(I+b’),a,b是控制亮度和对比度的任意常数。当Q超出范围怎么办?例如用8位表示像素值时,Q超出0~255,那么输出怎么办?默认情况下只取8位最低有效位并且忽略任何会导致值超出范围的溢出位。通常还需要进行饱和或者裁剪到极值效果会更好。


直方图操作。使用直方图的图像处理有两个相关的主要步骤。第一步是建立直方图,第二步是从直方图中提取数据并用它来处理图像。A建立直方图:对每个像素值累计计数。通过计数器数组完成计算每个像素值出现的次数。这个方法的缺点是占用的硬件资源比较多,适合阈值后的直方图计算。可以使用双口存储器实现,可以大大减少逻辑资源的使用。B直方图均衡化(使用局部信息来分配那些在输出像素值的范围上具有大的计数值的输入值的像素来获得更平坦的直方图):实现直方图均衡化的映射是归一化累积直方图。直观地,如果输入点集合的计数值大于平均值,那么映射的斜率大于1,反之,小于1。

 

局部滤波器。局部滤波器扩展点操作,以一个局部窗口内像素值的函数运算结果作为输出。窗口的大小、形状可以随意,但是一般都是采用奇数正方形的,我见过最多的就是3x3,5x5,7x7,这样的话中心就很容易确定。局部滤波器有去噪、边缘检测、边缘增强等。线性去噪有排序去噪,均值去噪,加权均值去噪等,边缘检测可以利用Prewitt,Sobel算子等,将这些算法在3x3窗口中实现,相对来说就比较容易了。也可以改进这些算法,是写小论文比较好的创新点。还有一些形态学滤波器,颜色滤波器,大致思想都一样,就是实现的时候算法改一下。

 


本文载自http://www.eefocus.com/fpga/410120/r0,如涉及侵权,请私信小编删除。

============华 丽 的 分 割 线============


想加入我们FPGA学习交流群吗?可以长按或扫描以下二维码,审核通过后我们邀请您加入

这些微信群旨在打造一个提供给FPGA工程开发人员及兴趣爱好者(统称“FPGAer”)进行技术交流、答疑解惑和学习的平台。而且我们也将会通过网络举办FPGA技术讲座,分享相关研究文献 



了解更多FPGA知识可以长按或扫描以下二维码关注FPGAer俱乐部




没有更多推荐了,返回首页