精华内容
下载资源
问答
  • 数字图像处理-高反差保留算法

    千次阅读 2019-08-16 15:32:13
    反差保留算法就是保留原图中反差比较大的地方,比如,一幅人脸图像中,反差比较大的地方就是五官了,在进行人脸美化的时候我们通常会对原图进行平滑处理,然而处理完之后丢失了图片的细节信息,因此在另一边我们...

    高反差保留算法

    高反差保留算法就是保留原图中反差比较大的地方,比如,一幅人脸图像中,反差比较大的地方就是五官了,在进行人脸美化的时候我们通常会对原图进行平滑处理,然而处理完之后丢失了图片的细节信息,因此在另一边我们通过会通过高反差保留或者其他高通滤波器保留图片的细节信息,然后将平滑之后的图像和高频图像进行光线性混合,可以得到更好的效果。
    具体到高反差保留算法,先使用高斯滤波器对图像进行平滑,高斯滤波器对边缘的平滑作用更加明显,使用原图减去高斯平滑之后的图,就得到强化边缘值。通过调节高斯模糊的半径可以控制得到的边缘的强度

     那么高反差保留算法本身的执行过程是如何的呢,简单的表达就是: 

             高反差保留 = 原始图像 - 高斯模糊图像 + 127

    加上127的目的是为了不让太多的像素由于不在有效范围内而导致图像太黑,从而丢失信息。

    推导原理

    从图中可以看出来, 

    由此我们可以推论出如下的计算公式:
    原始-高斯模糊=高反差保留
    运用数学知识可以得到:
    原始=高反差保留+高斯模糊
      这就意味着我们可以将任何一幅图像分成两部分:高斯模糊部分和高反差保留部分,两部分互相补充形成
    一幅完整的图像。
      我们进行一下扩展思考可以得到一种新的思路:高反差与低反差互补,锐化就和模糊互补(也难怪在PS中
    找不到“低反差”滤镜。),也确实如此:
         原始图像=高反差+低反差
         原始图像=锐化+模糊
      最后回到我们的PS文件,做一下逆向操作:将原始层移到最上面,按Ctrl+I将图层“高斯10”反相,
    图层模式改为正常,不透明度改回100%;将图层“高反差10”的图层模式改为线性光,不透明度改为50%,你会
    发现图像被还原了。
      结论:
      一、一幅图像可以被看作是互补的两部分:高斯模糊部分与高反差保留部分。
      二、线性光图层模式可以将两图层加在一起。
      三、我们改变这两部分任何一部分的参数,图像将会变得模糊或锐化。

    熟悉理解这个理论,对你日后修正模糊的图像很有帮助。

    通过高反差保留算法也可以实现图像增强的效果

       很多图像都需要增强,特别是一些医学图像,由于拍摄的硬件或拍摄的场合不理想,得到的图像往往细节都被隐藏起来,因此,细节的增强显得尤为重要,而原图 - 高斯模糊正好是图像的细节部位的信息的一种表达,因此,如果在模糊图的基础上再加上这个细节, 则即减少了噪音,又保持了边缘等细节(边缘和噪音都属于高频部分的),能有效的增强图像的信息。  

          因此,如果用这样的方式来得到一副图像:

          增强图像 = 模糊图像 + Amount *(原始图像 - 高斯模糊图像)

          则能起到一定的增强作用。 

     

    参考文章:

    https://www.cnblogs.com/lanye/p/3777303.html

    http://www.360doc.com/content/12/0223/09/1299947_188816702.shtml

    https://www.jianshu.com/p/bb702124d2ad

    https://blog.csdn.net/c80486/article/details/52506429

    展开全文
  • 对焦原理之反差式对焦    通常意义上来说,得到一张清晰合焦的照片,是我们摄影的基本功。而这一切,都需要一个必经的过程——对焦。这是一个很基础,但又很关键的操作,虽然对于我们所能接触的绝大多数相机手机...

    对焦原理之反差式对焦
       通常意义上来说,得到一张清晰合焦的照片,是我们摄影的基本功。而这一切,都需要一个必经的过程——对焦。这是一个很基础,但又很关键的操作,虽然对于我们所能接触的绝大多数相机手机等可以拍照的设备而言,半按快门甚至是触摸一下屏幕,即可完成这个过程。
       但对焦这一操作又是如何实现的呢?目前在手机上采用的自动对焦系统包括反差对焦、相位对焦和激光对焦三种方案,下面我们来看一下它们的工作原理和相互之间的区别是什么。
        这篇博客介绍反差对焦,其余两种对焦方式请关注博客   相位对焦   激光对焦
    反差对焦【CDAF】- Contrast Detection Auto Focus
       反差对焦是目前普及率最高、使用最广泛、成本相对较低的自动对焦技术,它又被成为对比度对焦。对焦的过程就是通过移动镜片来使对焦区域的图像达到最清晰的过程,所以对焦成功以后,直观的感受就是焦点的清晰度最高,而焦点以外的区域则表现为相对模糊状态。

    [原理]
        采用反差对焦的相机,当我们对准被摄物体时,镜头模组内的马达便会驱动镜片从底部向顶部移动,在这个过程中,像素传感器将会对整个场景范围进行纵深方向上的全面检测,并持续记录对比度等反差数值。找出反差最大位置后,运动到顶部的镜片则会重新回到该位置,完成最终的对焦。所以使用反差对焦的手机在拍照的过程中,如果取景框中的物体位置、内容发生变动,我们的肉眼就可以观察到屏幕上的内容会由模糊到清晰再到模糊的过程,有一种镜片在前后推拉的直观感受。
      首先有个概念要明确,任何对焦点都不是点,而是一个小平面,对应着传感器上一小片面积的像素的总和,这是讨论对焦这种话题的基础概念,千万不可理解成一个对焦点是一个对焦像素,谬之千里。

      市面上的无反机身,一个对焦框内对应传感器上像素大约150×150 。如果相机对焦模式选择单点对焦,理论上机身采集来自传感器数据中对应这个对焦框内的150*150个像素来计算反差程度。然后用一个最简单的公式来评估这个小区域内的反差:

    道理很简单,对焦框内依次做相邻两个像素的亮度差值,然后把所有差值求和,取倒数。图像越接近合焦局部反差越大,相邻两个像素数值差值越大,分母越大公式计算结果越小;人为设定一个数值范围,小于此值就认为合焦了。
      简单起见,在图像中选一小块区域转换成黑白模式,处理成与CMOS像素密度接近的马赛克方格,然后转换后得到右边的一组数值:

    分析方法不一定就是上边这种算法,比如可以统计出这些数据从大到小的分布,找出最大值与最小值的差值,理论上越不合焦这个差值就越小,越接近合焦差值就越大(反差大)。
      反差对焦的过程大概的步骤:

      在图中位置1,读取一张局部图像,然后根据上述公式计算出反差系数Kc , 如果数值不在合焦可接受范围内,那么就让镜头再转动一下到2,然后再判断,还不满足就再转此时的方向根据与1的对比可知是正确的,然后继续沿着这个方向转动,可能转动到3,再次计算,如果发现比2更不清楚了说明转过头了,需要掉转方向,转动量要小于2->3 的量;转动到4 再计算,还不满足,然后再判断一下方向,有可能会朝着2的方向转动也有可能向着5的方向。 最终可能落到合焦范围内停止。 总的过程就是不断比较尝试,一步比一步小,如果不给设定个合焦的数值标准界限,可能永远摇摆不停下去。
    还有可能比较糟糕的执行过程:

    从位置1 ,发现不合焦,然后让镜头转动一下,因为并不知道往哪个方向转动是合焦方向,那么很有可能一下转动到2的位置,然后发现更模糊了。。回头走,而且要退回比1->2更远的位置去,然后到了3;到了3发现,还是不够合焦,那么还要继续转动,因为此时还是不知道往哪个方向转动更接近合焦,那么有可能转动到4,然后又发现错了错了更模糊了。。回头走,但是退回的步子要介于1-3之间才可以,然后到了5…………然后执行到7->8 ,发现位置7和8模糊程度一样,那么就可以判断,7和8之间的位置是合焦位置,这样就找到了位置9,合焦。程序需要记住每次执行计算时的镜头位置,每次回退都不会比这个边界更大,理论上这样能越来越收敛,最终到合焦位置。
      对焦点搜索过程基本就是一个一维凸函数求极点,比较有效率的方法是斐波那契法,每次迭代最小能缩小最大区间0.382倍的长度。不过如果凸函数比较明确的话可能二次插值会更快点,用上述方法每次迭代都能保证缩小区间,这样就不会出现1->2或者3->4这种向外搜索的情况。

    [缺点]
      因为反差对焦的工作方式是进行对比度检测,因此相机镜片必须要前后移动完整记录所有的图像信息,然后计算出对比度最高的位置,才能最终完成对焦,所以反差对焦的一个主要缺点就是耗费的时间较长。要实现高速,需要软硬件结合。
      首先,它需要感光器的采样帧率尽可能的高,其二,对焦马达的相应速度也需要足够的快,要和感光器的采样帧率配得上,第三,算法也很重要,优秀的算法可以提供尽可能最优化的效率。

    展开全文
  • 1、灰度图像反差 int gray = gray_src.at(row, col); &nbsp //得到像素点的值 gray_src.at(row, col)=255-gray;//反差 int main(int argc,char**argv) { Mat src,gray_src; src = imread("D:/PT/test.jpg");...

    一、反差:

    1、灰度图像反差

    int gray = gray_src.at(row, col); &nbsp //得到像素点的值
    gray_src.at(row, col)=255-gray;//反差

    演示代码:
    
    int main(int argc,char**argv)
    {
    	Mat src,gray_src;
    	src = imread("D:/PT/test.jpg");
    	if (src.empty())
    	{
    		cout << "liangliang" << endl;
    		return -1;
    	}
    	namedWindow("input", CV_WINDOW_AUTOSIZE);
    	imshow("input", src);
    	//cvtColor(src, gray_src, CV_BGR2GRAY);
    	//namedWindow("output", CV_WINDOW_AUTOSIZE);
    	//imshow("output", gray_src);
    	int height = gray_src.rows;
    	int width = gray_src.cols;
     	for (int row = 0; row < height; row++)
    	{
    		for (int col = 0; col < width; col++)
    		{
    			int gray = gray_src.at<uchar>(row, col);
    			gray_src.at<uchar>(row, col)=255-gray;//反差
    		}
    	}
    	namedWindow("output", CV_WINDOW_AUTOSIZE);
    	imshow("output", gray_src);
    	//waitKey(2000);
    	//destroyWindow("output");   //等两秒自动销毁
    	waitKey(0);
    	return 0;
    

    2、彩色图像反差

    	printf("src=%d", src.cols);
    	cvtColor(src, gray_src, CV_BGR2GRAY); 
    	printf("gray_src=%d", gray_src.cols);
    
    彩色图像的cols和灰度图像的cols是一样的,此图为证:

    在这里插入图片描述

    #include<iostream>
    #include<opencv2/opencv.hpp>
    using namespace std;
    using namespace cv;
    
    int main(int argc,char**argv)
    {
    	Mat src,gray_src;
    	src = imread("D:/PT/test.jpg");
    	if (src.empty())
    	{
    		cout << "liangliang" << endl;
    		return -1;
    	}
    	//printf("src=%d", src.cols);
    	//cvtColor(src, gray_src, CV_BGR2GRAY); 
    	//printf("gray_src=%d", gray_src.cols);
    	Mat dst,dst2;
    	dst.create(src.size(), src.type());
    	dst2.create(src.size(), src.type());
    	int height = src.rows;
    	int width = src.cols;
    	int nc = src.channels();
    	for (int row = 0; row < height; row++)
    	{
    		for (int col = 0; col < width; col++)
    		{
    			if (nc == 1)
    			{
    				int gray = gray_src.at<uchar>(row, col);
    				gray_src.at<uchar>(row, col) = 255 - gray;//反差
    			}
    			else if (nc == 3)
    			{
    
    				int b = src.at<Vec3b>(row, col)[0];
    				int g = src.at<Vec3b>(row, col)[1];
    				int r = src.at<Vec3b>(row, col)[2];        //彩色图像的cols和灰度图像的cols是一样的
    				dst.at<Vec3b>(row, col )[0]= 255 - b;
    				dst.at<Vec3b>(row, col)[1] = 255 - g;
    				dst.at<Vec3b>(row, col)[2] = 255 - r;
    
    				//dst2.at<Vec3b>(row, col)[0] = b;
    				//dst2.at<Vec3b>(row, col)[1] = g;
    				//dst2.at<Vec3b>(row, col)[2] = r;
    
    				gray_src.at<uchar>(row, col) = min(r, min(b, g));
    			}
    			
    		}
    	}
    	namedWindow("output", CV_WINDOW_AUTOSIZE);
    	imshow("output", gray_src);
    	//waitKey(2000);
    	//destroyWindow("output");
    	waitKey(0);
    	return 0;
    }
    

    API实现:

    	bitwise_not(src, dst);
    	namedWindow("output2", CV_WINDOW_AUTOSIZE);
    

    在这里插入图片描述

    在这里插入图片描述

    二、混合:

    相关API (addWeighted)

    理论-线性混合操作

    演示代码:
    //图像混合
    Mat src1, src2, dest;
    src1 = imread("D:/vcprojects/images/LinuxLogo.jpg");
    src2 = imread("D:/vcprojects/images/win7logo.jpg");
    if (!src1.data) {
    	printf("could not load LinuxLogo image...\n");
    	return -1;
    }
    if (!src2.data) {
    	printf("could not load win7logo image...\n");
    	return -1;
    }
    if (src1.rows == src2.rows && src1.cols == src2.cols) {
    	double alpha = 0.5;
    	namedWindow("line-blend", CV_WINDOW_AUTOSIZE);
    	addWeighted(src1, (1 - alpha), src2, alpha, 0.0, dest);
    
    	imshow("line-blend", dest);
    	waitKey(0);
    	return 0;
    }
    else {
    	printf("image size is not same...\n");
    	return -1;
    }
    

    三、调整图像亮度与对比度:

    演示代码:
    //调整图像对比度
    #include<iostream>
    #include<opencv2/opencv.hpp>
    using namespace std;
    using namespace cv;
    
    int main(int argc, char** argv)
    {
    	Mat src, dst;
    	src = imread("D:/PT/liner2.jpg");
    	if (!src.data)
    	{
    		cout << "liangliang" << endl;
    		return -1;
    	}
    	char input_win[] = "input image";
    	//cvtColor(src, src, COLOR_BGR2GRAY);
    	namedWindow("input_win", CV_WINDOW_AUTOSIZE);
    	imshow("input_win", src);
    	
    	int height = src.rows;
    	int width = src.cols;
    	dst = Mat::zeros(src.size(), src.type());
    	float alpha = 0.4;
    	float beta = 10;
    	Mat m1;
    	//src.convertTo(m1, CV_32F);
    	for(int row=0;row<height;row++)
    		for (int col = 0; col < width; col++)
    		{
    			if (src.channels() == 3)
    			{
    				float b = src.at<Vec3b>(row, col)[0];
    				float g = src.at<Vec3b>(row, col)[1];
    				float r = src.at<Vec3b>(row, col)[2];
    				dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b * alpha + beta);
    				dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g * alpha + beta);
    				dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r * alpha + beta);
    			}
    			else if (src.channels() == 1)
    			{
    				float v = src.at<uchar>(row, col);
    				dst.at<uchar>(row, col) = saturate_cast<uchar>(v * alpha + beta);
    			}
    		}
    	char output_title[] = "contrast and brightness change demo";
    	namedWindow("output_title", CV_WINDOW_AUTOSIZE); 
    	imshow("output_title", dst);
    	waitKey(-1);
    	return 0;
    }
    

    在这里插入图片描述
    在这里插入图片描述

    四、绘制文字:

    随机数生成cv::RNG:
    • 生成高斯随机数gaussian (double sigma)
    • 生成正态分布随机数uniform (int a, int b)
    putText函数中设置fontFace(cv::HersheyFonts) :
    • fontFace, CV_FONT_HERSHEY_PLAIN
    • fontScale , 1.0, 2.0~ 8.0
    opencv字体:
    标志名称描述
    CV_FONT_HERSHEY_SIMPLEX正常尺寸sans-serif字体
    CV_FONT_HERSHEY_PLAIN小尺寸sans-serif字体
    CV_FONT_HERSHEY_DUPLEX正常尺寸sans-serif, 比CV_FONT_HERSHEY_SIMPLEX更复杂
    CV_FONT_HERSHEY_COMPLEX正常尺寸serif, 比CV_FONT_HERSHEY_DUPLE更复杂
    CV_FONT_HERSHEY_TRIPLEX正常尺寸serif, 比CV_FONT_HERSHEY_COMPLEX更复杂
    CV_FONT_HERSHEY_COMPLEX_SMALLCV_FONT_HERSHEY_SCRIPT_SIMPLEX
    CV_FONT_HERSHEY_SCRIPT_COMPLEXCV_FONT_HERSHEY_SCRIPT_SIMPLEX更复杂的风格
    OpenCV中用RNG产生随机数(C++):

    产生随机数是编程中经常要用到的操作。C和C++中产生随机数的方法如rand()、 srand() 等在OpenCV中仍可以用。此外,OpenCV还特地编写了C++的随机数类RNG,C的随机数类CvRNG,还有一些相关的函数,使用起来更加方便。

    说明
    1、关键字前带cv的都是C里的写法,不带cv的是C++里的写法,比如CvRNG和RNG,其本质都是一样的。
    2、计算机产生的随机数都是伪随机数,是根据种子seed和特定算法计算出来的。所以,只要种子一定,算法一定,产生的随机数是相同的
    3、要想产生完全不重复的随机数,可以用系统时间做种子。OpenCV中用GetTickCount(),C 中用time()

    OpenCV中的C++版本随机数:

    RNG类是opencv里C++的随机数产生器。它可产生一个64位的int随机数。目前可按均匀分布和高斯分布产生随机数。随机数的产生采用的是Multiply-With-Carry算法和Ziggurat算法。
    1、产生一个随机数:

     RNG  可以产生3种随机数
     
     RNG(int seed)         使用种子seed产生一个64位随机整数,默认-1
     RNG::uniform( )       产生一个均匀分布的随机数
     RNG::gaussian( )      产生一个高斯分布的随机数
    

    注:
    RNG::uniform(a, b ) 返回一个[a,b)范围的均匀分布的随机数,a,b的数据类型要一致,而且必须是int、float、double中的一种,默认是int。
    RNG::gaussian( σ) 返回一个均值为0,标准差为σ的随机数。
             如果要产生均值为λ,标准差为σ的随机数,可以λ+ RNG::gaussian( σ)

    //创建RNG对象,使用默认种子“-1”  
    RNG rng; 
    
    //产生64位整数  
    int N1 = rng; 
    
    /*-------------产生均匀分布的随机数uniform和高斯分布的随机数gaussian---------*/  
    //总是得到double类型数据0.000000,因为会调用uniform(int,int),只会取整数,所以只产生0   
    double N1a = rng.uniform(0,1);  
    
    //产生[0,1)范围内均匀分布的double类型数据  
    double N1b = rng.uniform((double)0,(double)1); 
    
    //产生[0,1)范围内均匀分布的float类型数据,注意被自动转换为double了。  
    double N1c = rng.uniform(0.f,1.f); 
    
    //产生[0,1)范围内均匀分布的double类型数据。  
    double N1d = rng.uniform(0.,1.); 
    
    //可能会因为重载导致编译不通过(确实没通过。。)     
    //double N1e = rng.uniform(0,0.999999); 
    
    //产生符合均值为0,标准差为2的高斯分布的随机数  
    double N1g = rng.gaussian(2); 
    
    

    注:rng既是一个RNG对象,也是一个随机整数。

    2、返回下一个随机数:

    上面一次只能返回一个随机数,实际上系统已经生成一个随机数组。如果我们要连续获得随机数,没有必要重新定义一个RNG类,只需要取出随机数组的下一个随机数即可。

    RNG rng;
    int N2 = rng.next();                    //返回下一个随机整数,即N1.next(); 
    //返回下一个指定类型的随机数
    int N2a = rng.operator uchar();         //返回下一个无符号字符数
    int N2b = rng.operator schar();         //返回下一个有符号字符数
    int N2c = rng.operator ushort();        //返回下一个无符号短型
    int N2d = rng.operator short int();     //返回下一个短整型数
    int N2e = rng.operator int();           //返回下一个整型数 
    int N2f = rng.operator unsigned int();  //返回下一个无符号整型数
    int N2g = rng.operator float();         //返回下一个浮点数 
    int N2h = rng.operator double();        //返回下一个double型数
    int N2i = rng.operator ()();            //和rng.next( )等价
    int N2j = rng.operator ()(100);         //返回[0,100)范围内的随机数 
    
    

    3、用随机数填充矩阵 RNG::fill( ):

    void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange=false );
    
    参数说明:
    InputOutputArray                    输入输出矩阵,最多支持4通道,超过4通道先用reshape()改变结构
    int distType                        UNIFORM 或 NORMAL,表示均匀分布和高斯分布
    InputArray a                           disType是UNIFORM,a表示为下界(闭区间);disType是NORMAL,a均值
    InputArray b                           disType是UNIFORM,b表示为上界(开区间);disType是NORMAL,b标准差
    bool saturateRange=false     
    	只针对均匀分布有效。当为真的时候,会先把产生随机数的范围变换到数据类型的范围,再产生随机数;
    	如果为假,会先产生随机数,再进行截断到数据类型的有效区间。请看以下fillM1和fillM2的例子并观察结果 
    
    
    //产生[1,1000)均匀分布的int随机数填充fillM  
    Mat_<int>fillM(3,3);
    rng.fill(fillM,RNG::UNIFORM,1,1000);  
    
    Mat fillM1(3,3,CV_8U); 
    rng.fill(fillM1,RNG::UNIFORM,1,1000,TRUE); 
    
    Mat fillM2(3,3,CV_8U); 
    rng.fill(fillM2,RNG::UNIFORM,1,1000,FALSE); 
    
    //fillM1产生的数据都在[0,,255)内,且小于255;
    //fillM2产生的数据虽然也在同样范围内,但是由于用了截断操作,所以很多数据都是255,  
    
    //产生均值为1,标准差为3的随机double数填进fillN  
    Mat_<double>fillN(3,3); 
    rng.fill(fillN,RNG::NORMAL,1,3);
    
    

    4、RNG& rng=theRNG();

    RNG& rng=theRNG();
    double x= (double)rng;
    float  y= (float)rng;
    int    z= (int)rng;
    
    

    5、产生不重复的随机数:
    采取另一种方式,用系统时间作为种子初始化rng

    RNG rng((unsigned)time(NULL));//当然,用这个要记得加上头函数<time.h>
    
    

    开始生成随机数

    double x=rng.uniform((double)0,(double)255);
    float y=rng.uniform(0.f,255.f);
    int z=rng.uniform((int)0, (int)255 );
    
    

    6、randShuffle( ) 将原数组(矩阵)打乱:

    randShuffle
    ( 
    	InputOutputArray dst,     输入输出数组(一维)
        double iterFactor=1. ,     决定交换数值的行列的位置的一个系数...
        RNG* rng=0               (可选)随机数产生器,0表示使用默认的随机数产生器,即seed=-1。rng决定了打乱的方法
    )
    
    puttext演示代码:
    #include<iostream>
    #include<opencv2/opencv.hpp>
    using namespace std;
    using namespace cv;
    
    Mat src, bgImage;
    void Myline();
    void MyRectangle();
    void MyEllipse();
    void MyCircle();
    void Mypolygon();
    void RandomLineDemo();
    int main(int argc, char** argv)
    {
    	
    	src = imread("D:/PT/dln.jpg");
    	if (src.empty())
    	{
    		cout << "liangliang" << endl;
    		return -1;
    	}
    	double scale = 0.5;
    	Size dsize = Size(src.cols * scale, src.rows * scale);
    	Mat dst = Mat(dsize, CV_32S);
    	resize(src, bgImage, dsize);
    
    	Myline();//画线
    	MyRectangle();
    	MyEllipse();
    	MyCircle();
    	Mypolygon();
    
    	//putText(bgImage, "Hello OpenCV", Point(bgImage.cols / 2, bgImage.rows / 2), CV_FONT_HERSHEY_COMPLEX, 3.0, Scalar(12, 255, 200), 3, 8);
    	//尺寸因子,颜色,线条宽度,线型(4邻域,8邻域)
    	                                                                                                   //大小                       宽度
    	namedWindow("input", CV_WINDOW_AUTOSIZE);
    	imshow("input", bgImage);
    	//RandomLineDemo();
    	waitKey(0);
    	return 0;
    }
    
    
    void Myline()//画线
    {
    	Point p1 = Point(20, 30);
    	Point p2;
    	p2.x = 300;
    	p2.y = 300;
    	Scalar color = Scalar(0, 0, 255);
    	line(bgImage, p1, p2, color, 8, LINE_AA);//4,8
    	//8邻接,4邻接,AA高斯滤波
    }
    
    void MyRectangle()//矩形
    {
    	Rect rect = Rect(200, 100, 300, 300);//起始位置,宽高
    	Scalar color = Scalar(255, 0, 0);
    	rectangle(bgImage,rect,color,2,LINE_8);
    }
    void MyEllipse()//椭圆
    {
    	Scalar color = Scalar(0, 255, 0);
    	ellipse(bgImage, Point(bgImage.cols / 2, bgImage.rows / 2), Size(bgImage.cols / 4, bgImage.rows / 8), 30, 0, 160, color, 2, LINE_8);
    	                                                                                      //椭圆是angle 角度,椭圆在0和360度之间延伸一个弧
    }
    void MyCircle()//圆形
    {
    
    	Scalar color = Scalar(0, 255, 255);
    	Point center = Point(bgImage.cols / 2, bgImage.rows / 2);
    	circle(bgImage, center, 300, color, 2, LINE_8);
    }
    void Mypolygon()//填充
    {
    	Point pts[1][5];
    	pts[0][0] = Point(100, 100);
    	pts[0][1] = Point(100, 200);
    	pts[0][2] = Point(200, 200);
    	pts[0][3] = Point(200, 100);
    	pts[0][4] = Point(100, 100);
    
    	const Point* ppts[] = { pts[0] };//定义指针
    	int npt[] = { 5 };//定义指针数,绘制顶点的数目
    	Scalar color = Scalar(255, 12, 255);
    	fillPoly(bgImage, ppts, npt, 1, color, 8);
    }
    
    void RandomLineDemo()
    {
    	RNG rng(12345);
    	Point pt1;
    	Point pt2;
    	Mat bg = Mat::zeros(bgImage.size(), bgImage.type());
    	namedWindow("randow line demo", CV_WINDOW_AUTOSIZE);
    	for (int i = 0; i < 100000; i++)
    	{
    		pt1.x = rng.uniform(0, bgImage.cols);
    		pt2.x = rng.uniform(0, bgImage.cols);
    		pt1.y = rng.uniform(0, bgImage.rows);
    		pt2.y = rng.uniform(0, bgImage.rows);
    		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    		if (waitKey(50) == 0)
    		{
    			break;
    		}
    		line(bg, pt1, pt2, color, 1, 8);
    		imshow("randow line demo", bg);
    	}
    
    }
    
    

    在这里插入图片描述

    展开全文
  • 图像处理技术(一)图像处理基础知识

    万次阅读 多人点赞 2018-08-30 15:52:26
    1.1基本概念 图像处理的概念是对图像信息进行加工处理,以满足人的视觉心理和实际应用的需求。 模拟图像:连续图像,采用数字化(离散化)表示和数字技术处理之前的...图像增强:调整图像的对比度,突出重要细节,...

    1.1基本概念

    图像处理的概念是对图像信息进行加工处理,以满足人的视觉心理和实际应用的需求。

    模拟图像:连续图像,采用数字化(离散化)表示和数字技术处理之前的图像。

    数字图像:由连续的模拟图像采样和量化而得的图像,组成其基本单位是像素。

    像素的值代表图像在该位置的亮度或灰度,称为图像的灰度值。

    数字图像像素具有整数坐标和整数灰度值。

    1.2

    图像增强:调整图像的对比度,突出重要细节,改善图像质量。

    图像复原和校正:去噪声、去模糊。使得图像能够尽可能地贴近原始图像。

    图像的平滑:图像的去噪声处理(通过滤波算法),为了去除实际成像过程中,因成像设备和环境所造成的图像失真,提取有用的信息。

    边缘锐化:加强图像的轮廓边缘和细节(一般轮廓边缘都处于灰度突变的地方),通过基于微分锐化算法使灰度反差增强。

    图像分割:图像分割就是把图像分成若干个特定的、具有独特性质的区域。

    2.1

    计算机图像处理的几个内容:

    如何对模拟图像进行采样、量化以产生数字图像?

    如何压缩图像数据以便存储和传输?

    如何对数字图像做各种变换以方便处理?

    采样是空间上的离散化,量化是灰度上的离散化。

    图像采样就是在水平和垂直方向上等分隔地分割成网状。

    量化是在每个采样点上进行的,所以必须先采样后量化。两者都是图像数字化不可或缺的两个操作,两者紧密相关,同时完成。

    图像量化实际就是将图像采样后的样本值的范围分为有限多个区域,落入某区域中的值用同一值表示,从而用有限的离散数值量来代替无限的连续模拟量。量化时确定的离散取值个数称为量化级数,表示量化的色彩和亮度值所需的二进制位数称为量化字长,一般量化字长为8位、16位或24位,量化字长越大,越能真实反映原有图像的颜色,但存储的字节也越大。

    M、N图像尺寸,K每个像素所具有的离散灰度级数(不同灰度值的个数)

    存一幅图像所需的位数(bit)B=M*N*K 减少K值能增强图像的反差。

    LENA图是永恒的经典,图像处理领域使用最为广泛的标准测试图。

    2.2

    图像模式:

    1、灰度图像:每个像素的信息由一个量化的灰度级来描述的图像,无彩色信息。

    2、黑白图像、二值图像:只有黑白两色没有中间的过渡,像素值为0、1。

    3、彩色图像:数据多采用RGB三基色模型,包含亮度和颜色两类信息。

    色彩的三要素包括色调(光波的不同波长,反映不同颜色的种类)、饱和度(颜色的纯度,颜色的深浅程度)、亮度(光的明亮程度)。HSL模型

     

    2.3

    图像文件格式:

    BMP文件格式 位图文件格式 由文件头、调色板数据、图像数据三部分组成

    GIF  文件格式 存储256色图像

    TIFF 文件格式 相对经典、功能很强的图像文件存储格式

    JPEG文件格式 静止图像压缩标准文件格式

    DICOM  格式 医学图像文件存储格式

    2.4图像质量评价

    客观评价标准:归一化均方误差NMSE、峰值均方误差PMSE、等效信噪比PSNR

    主观评价标准:图像逼真度、图像可懂度

    展开全文
  • 本文将介绍数字图像处理中两个基本内容---图像亮度对比度,详细讲解两种基本的亮度对比度调节算法,并使用C语言进行算法实现,在教会初学者算法的同时,不依赖任何第三方库编程实现,学以致用且易学易用。
  • 今天,我们就一起来测试对比度在吸引关注中的作用。从柔和、平静的绿色转变到激烈、鲜艳的红色可以吸引来更多的关注。当然,这也不一定有效。如果没有铺垫好基础使其突出,那么吸引力将会大大下降。这种情况下的...
  • PS通道高反差保留计算人物磨皮技巧

    千次阅读 2020-10-22 17:58:53
    2.脸部比较糙,主要是因为明暗差距太大,打开通道,其中蓝通道对比最强,复制蓝通道,利用滤镜-其他-高反差保留(10)让面部问题暴露出来 3.仍然不够明显,可以利用图像-计算通过两个蓝副本线性光的混合
  • 图像直方图之图像对比

    万次阅读 2018-08-14 21:51:48
    图像直方图之图像对比度 直方图也可以描述图像对比度的情况。对比度是衡量某一图像某一场景中亮区域和暗区域之间亮度差异的尺度。宽广的直方图可以反映某一图像具有较高对比度,反之,较为窄小的直方图反映了某一...
  • 本文从Fresne1-Kirchhoff衍射公式出发,直接由光强分布导出了散斑平均反差与表面粗糙度特征参数的关系公式,采用指数形式和高斯形式的自相关函数,得到极为相符的计算结果。利用激光衍射散斑平均反差测量表面粗糙度,...
  • 锐化(高反差保留)

    千次阅读 2015-10-23 22:35:12
    反差保留,就是过滤出一些高对比的部份来处理,主要就是影像的边缘/轮廓部份。保留图像上像素与周围反差比较大的部分,其它的部分都变为灰色。例如人像就保留了眼睛、嘴、痘痘及身体轮廓等 1.复制一个图层Ctrl+...
  • 手机拍照反差对焦、相位对焦和激光对焦系统解析 参考网址:https://jingyan.baidu.com/article/22a299b5c882a29e19376aad.html 手机拍照三大对焦系统解析#资料课代表| 讲窍门# 你最常使用的拍照工具是什么?...
  • 图像处理之对比度增强

    千次阅读 2020-11-25 21:39:04
    文章目录对比度增强一、对比度增强的方法?二、使用步骤1.引入库2.读入数据总结 对比度增强 在图像处理中,由于获取的图像质量不好,需要通过对比度增强来提升图片质量,主要解决的是由于图像灰度级范围较小造成的...
  • 清晰度、对比度和锐化程度的调整,是照片后期的三个重要步骤。它们容易混淆,但各自... 对比度是指的画面的明暗反差程度。增加对比度,画面中亮的地方会更亮,暗的地方会更暗,明暗反差增强。  为了更好的解释...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,711
精华内容 1,884
关键字:

反差对比