zoukankan      html  css  js  c++  java
  • 一步步实现看图工具(四)

    
    

    今天加入了一些新功能:

    1. YUV文件格式支持(yuv420p 420sp, yuv422, yuv444) 

    2. 亮度,色调,饱和度,对比度的调整。

    3. 反色,灰度,阈值化操作。

    4. 加入历史记录,以支持回退、前进等操作。

    5. LOG模块和快捷键等等。

    YUV文件格式支持

       不了解YUV格式的同学可以先看看这个:

       http://zh.wikipedia.org/wiki/YUV

       Opencv提供了YUV的转换函数, 但是色彩会有些损失。所以根据公式自己写了一个。 我这个是最近邻插值算法,相对于双线性或者双三次插值比较简单。 感兴趣的读者也可以自己实现。

    void _YUVtoBGR(Vec3b& rgb, const Vec3b& yuv)
    {
    	int Y = yuv[0];
    	int U = yuv[1] - 128;
    	int V = yuv[2] - 128;
    
    	int R = (int)( Y + 1.403f * V);
    	int G = (int)( Y - 0.344f * U - 0.714f * V);
    	int B = (int)( Y + 1.770f * U);
    
    	rgb[0]= saturate_cast<uchar>(B);
    	rgb[1]= saturate_cast<uchar>(G);
    	rgb[2]= saturate_cast<uchar>(R);
    }
    void _BGRtoYUV(const Vec3b& rgb, Vec3b& yuv)
    {
    	int B = rgb[0];
    	int G = rgb[1];
    	int R = rgb[2];
    	int Y = (int)(0.299f * R + 0.587f * G + 0.114f * B);
    	int U = (int)((B-Y) * 0.565f + 128);
    	int V = (int)((R-Y) * 0.713f + 128);
    
    	yuv[0]= saturate_cast<uchar>(Y);
    	yuv[1]= saturate_cast<uchar>(U);
    	yuv[2]= saturate_cast<uchar>(V);
    }
    
    
    void ImageYUV2BGR(Mat& img, PBYTE pYUV, int type)
    {
    	CFunctionLog fl(__FUNCTION__);
    	int w = img.cols;
    	int h = img.rows;
    	w = ALIGN_DOWN(w, 4);
    	h = ALIGN_DOWN(h, 4);
    	Vec3b yuv;
    	switch(type)
    	{
    	case YUV_NV21:
    	case YUV_NV12:
    		{
    			PBYTE pUV = pYUV+w*h;
    			PBYTE pY = pYUV;
    			int vidx = type == YUV_NV12 ? 1 : 2;
    			int uidx = type == YUV_NV12 ? 2 : 1;
    			for (int y = 0;y < h;y++)
    			{
    				for (int x = 0;x < w;x++)
    				{
    					yuv[0] = *pY++;
    					yuv[uidx] = pUV[y/2*w+x/2*2];
    					yuv[vidx] = pUV[y/2*w+x/2*2+1];
    					_YUVtoBGR(img.at<Vec3b>(y, x), yuv);
    				}
    			}
    		}
    		break;
    	case YUV_I420:
    	case YUV_YV12:
    		{
    			PBYTE pY = pYUV;
    			PBYTE pV = pYUV+w*h*5/4;
    			PBYTE pU = pYUV+w*h;
    			int uidx = type == YUV_I420 ? 1 : 2;
    			int vidx = type == YUV_I420 ? 2 : 1;
    			for (int y = 0;y < h;y++)
    			{
    				for (int x = 0;x < w;x++)
    				{
    					yuv[0] = *pY++;
    
    					yuv[uidx] = pU[y/4*w+x/2+w*y/4%2];
    					yuv[vidx] = pV[y/4*w+x/2+w*y/4%2];
    
    					_YUVtoBGR(img.at<Vec3b>(y, x), yuv);
    
    				}
    			}
    		}
    		break;
    	case YUV_YUYV:
    	case YUV_UYVY:
    		{
    			int yidx = type == YUV_YUYV ? 0 : 1;
    			int uidx = type == YUV_YUYV ? 1 : 0;
    			int vidx = type == YUV_YUYV ? 3 : 2;
    			PBYTE pY = pYUV + yidx;
    			PBYTE pV = pYUV + vidx;
    			PBYTE pU = pYUV + uidx;
    
    
    			for (int y = 0;y < h;y++)
    			{
    				for (int x = 0;x < w;x++)
    				{
    					yuv[0] = *pY;
    					pY+=2;
    					if(x%2==0) {
    						yuv[1] = *pU;
    						yuv[2] = *pV;
    						pU+=4;
    						pV+=4;
    					}
    					_YUVtoBGR(img.at<Vec3b>(y, x), yuv);
    				}
    			}
    		}
    		break;
    	case YUV_444:
    		{
    			PBYTE pY = pYUV;
    			PBYTE pU = pYUV + w*h;
    			PBYTE pV = pYUV + w*h*2;
    			for (int y = 0;y < h;y++)
    			{
    				for (int x = 0;x < w;x++)
    				{
    					yuv[0] = *pY++;
    					yuv[1] = *pU++;
    					yuv[2] = *pV++;
    					_YUVtoBGR(img.at<Vec3b>(y, x), yuv);
    				}
    			}
    		}
    		break;
    	}
    
    }
    
    void ImageBGR2YUV(Mat& img, PBYTE pYUV, int type)
    {
    	CFunctionLog fl(__FUNCTION__);
    	int w = img.cols;
    	int h = img.rows;
    	w = ALIGN_DOWN(w, 4);
    	h = ALIGN_DOWN(h, 4);
    	Vec3b yuv;
    	switch(type)
    	{
    
    	case YUV_NV21:
    	case YUV_NV12:
    		{
    			PBYTE pUV = pYUV+w*h;
    			PBYTE pY = pYUV;
    			int vidx = type == YUV_NV12 ? 1 : 2;
    			int uidx = type == YUV_NV12 ? 2 : 1;
    			for (int y = 0;y < h;y++)
    			{
    				for (int x = 0;x < w;x++)
    				{
    					Vec3b c = img.at<Vec3b>(y, x);
    					_BGRtoYUV(c, yuv);
    					*pY++ = yuv[0];
    					if(y%2==0&&x%2==0) {
    						pUV[y/2*w+x/2*2] = yuv[uidx];
    						pUV[y/2*w+x/2*2+1] = yuv[vidx];
    					}
    				}
    			}
    		}
    		break;
    	case YUV_I420:
    	case YUV_YV12:
    		{
    			PBYTE pY = pYUV;
    			PBYTE pV = pYUV+w*h*5/4;
    			PBYTE pU = pYUV+w*h;
    			int uidx = type == YUV_I420 ? 1 : 2;
    			int vidx = type == YUV_I420 ? 2 : 1;
    			for (int y = 0;y < h;y++)
    			{
    				for (int x = 0;x < w;x++)
    				{
    					Vec3b c = img.at<Vec3b>(y, x);
    					_BGRtoYUV(c, yuv);
    					*pY++ = yuv[0];
    					if(y%2==0&&x%2==0) {
    						*pU++ = yuv[uidx];
    						*pV++ = yuv[vidx];
    					}
    				}
    			}
    		}
    		break;
    	case YUV_YUYV:
    	case YUV_UYVY:
    		{
    			int yidx = type == YUV_YUYV ? 0 : 1;
    			int uidx = type == YUV_YUYV ? 1 : 0;
    			int vidx = type == YUV_YUYV ? 3 : 2;
    			PBYTE pY = pYUV + yidx;
    			PBYTE pV = pYUV + vidx;
    			PBYTE pU = pYUV + uidx;
    
    			for (int y = 0;y < h;y++)
    			{
    				for (int x = 0;x < w;x++)
    				{
    					Vec3b c = img.at<Vec3b>(y, x);
    					_BGRtoYUV(c, yuv);
    					*pY = yuv[0];
    					pY+=2;
    					if(x%2==0) {
    						*pU = yuv[1];
    						*pV = yuv[2];           
    						pU+=4;
    						pV+=4;
    					}
    
    				}
    			}
    		}
    		break;
    	case YUV_444:
    		{
    			PBYTE pY = pYUV;
    			PBYTE pU = pYUV + w*h;
    			PBYTE pV = pYUV + w*h*2;
    
    			for (int y = 0;y < h;y++)
    			{
    				for (int x = 0;x < w;x++)
    				{
    					Vec3b c = img.at<Vec3b>(y, x);
    					_BGRtoYUV(c, yuv);
    					*pY++ = yuv[0];
    					*pU++ = yuv[1];
    					*pV++ = yuv[2];
    				}
    			}
    		}
    		break;  
    	}
    }
    








    还是先来张原图:


    void Light(Mat& img, long brightness, long contrast)
    {
    	float c=(100 + contrast)/100.0f;
    	brightness+=128;
    
    	int dim(256);  
    	Mat lut(1,&dim,CV_8U);  
    
    	for(int i = 0; i < 256; i++)  
    	{  
    		lut.at<uchar>(i) = saturate_cast<uchar>((i-128)*c + brightness + 0.5f);
    	}  
    
    	LUT(img, lut, img);
    	return;
    }





    void Saturation(Mat& img, int sat)
    {
    	uchar tableUV[256];
    	float c=(100 + sat)/100.0f;
    	for(int i = 0; i < 256; i++)
    	{
    		tableUV[i] = saturate_cast<uchar>((i-128)*c + 128.5f);
    	}
    	int w = img.cols;
    	int h = img.rows;
    	int size = GetYUVSize(w, h, YUV_NV12);
    	uchar *pBuffer = new uchar[size];
    	ImageBGR2YUV(img, pBuffer, YUV_NV12);
    	int temp;
    	for(int i = w*h; i < size; i++)
    	{
    		temp = pBuffer[i];
    		pBuffer[i] = tableUV[temp];
    		
    	}
    	
    	ImageYUV2BGR(img, pBuffer, YUV_NV12);
    	delete pBuffer;
    }



    void Hue(Mat& img, int h)
    {
    	cvtColor(img, img, CV_BGR2HLS);
    	for(int x = 0; x < img.cols; x++)
    	{
    		for(int y = 0; y < img.rows; y++)
    		{
    			Vec3b c = img.at<Vec3b>(y, x);
    			c[0] = (c[0]+h)%256;
    			img.at<Vec3b>(y, x) = c;
    		}
    	}
    	cvtColor(img, img, CV_HLS2BGR);
    }



            case ID_COLOR_NEGATIVE:
    		dst= Scalar(255, 255, 255) - image;
    		break;
    	case ID_COLOR_GRAYSCALE:
    		cvtColor(image, dst, CV_BGR2GRAY);
    		cvtColor(dst, dst, CV_GRAY2BGR);
    		break;
    	case ID_COLOR_THRESHOLD:
    		cvtColor(image, dst, CV_BGR2GRAY);
    		threshold(dst, dst, 100, 255, CV_THRESH_OTSU | CV_THRESH_BINARY_INV);
    		cvtColor(dst, dst, CV_GRAY2BGR);
    



    源码已公开,大家可以一起来完善这个工具。有好的想法也可以Email: 2723367319@qq.com

    http://download.csdn.net/detail/fallingstar08/5747747


  • 相关阅读:
    django自带登录认证与登录自动跳转
    11月份草稿2
    使用JavaScript实现字符串格式化
    requests与BeautifulSoup
    python+minicap(二)
    python+minicap的使用
    python+opencv图像处理(一)
    haproxy实现mysql从库负载均衡
    mysql 5.7 64位 解压版安装
    Redis基础教程
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3188363.html
Copyright © 2011-2022 走看看