zoukankan      html  css  js  c++  java
  • 彩色图像的直方图绘制及灰度图像均衡化

    Mat容器

      Mat E = Mat :: eye(4,4,CV_64F);
      cout << “E =” << endl << “” << E << endl << endl;
      Mat O = Mat :: ones(2,2,CV_32F);
      cout << “O =” << endl << “” <<“O << endl << endl;
      Mat Z = Mat :: zeros(3,3,CV_8UC1);
      cout << “Z =” << endl << “” << Z << endl << endl;
    

    像素值读写的几种方法:

    • 方法一:

      1. 单通道读像素uchar value = grayimg.at<uchar>(i,j);

        for(int i=0;i<grayimg.rows;i++)
        {
          for(int j=0;j<grayimg.cols;j++)
          {
            grayimg.at<uchar>(i,j)=(i+j)%255;
          }
        }
        
      2. 彩色图像(BGR)-3通道

        for(int i=0;i<colorimg.rows;i++)
        {
          for(int j=0;j<colorimg.cols;j++) {
            Vec3b pixel;
            pixel[0]=i%255;//Blue
            pixel[1]=j%/255;//Green
            pixel[2]=0;//Red
            colorimg.at<Vec3b>(i,j)=pixel;
          }
        }
        
    • 方法二:

      1. 单通道读像素cv::Mat Iterator_<uchar>grayit,grayend;

        cv::Mat Iterator_<uchar> grayit,grayend;
        for(grayit = grayimg.begin<uchar>(),
        grayend = grayimg.end<uchar>();
        grayit != grayend;
        grayit++)
        {
            *grayit=rand()%255;
        }
        
      2. 彩色图像(BGR)-3通道

        MatIterator_<Vec3b> colorit,colorend;
        for(colorit=colorimg.begin<Vec3b>(),
        colorend=colorimg.end<Vec3>();
        colorit != colorend;
        colorit++) {
          (*colorit)[0]=rand()%255;//Blue
          (*colorit)[1]=rand()%255;//Green
          (*colorit)[2]=rand()%255;//Red
        }
        
    • 方法三:

      1. 单通道

        for(int i=0;i<grayimg.rows;i++)
        {
          //获取第i行首像素指针
          uchar *p=grayimg.ptr<uchar>(i);
          for(int j=0;j<grayimg.cols;j++)
          {
            //对第i行每个像素(byte)操作
            p[j] = (i+j)%255;
          }
        }
        

    彩色图像的直方图实现

    //绘制彩色图像的直方图
    void colorGraph()
    {
    	string src = "../img/tiger.jpg";
    	Mat img = imread(src,IMREAD_COLOR);
    	namedWindow("colorimg",WINDOW_AUTOSIZE);
    	imshow("colorimg",img);
    	Mat colorimg = Mat::zeros(600, 800, CV_8UC3);
    
    	//存放3个通道的各个灰度级像素数
    	vector<int> num0(256);
    	vector<int> num1(256);
    	vector<int> num2(256);
    
    	//遍历图形像素,
    	for (int i = 0; i < img.rows; i++)
    	{
    		for (int j = 0; j < img.cols; j++)
    		{
    			Vec3b pix;
    			pix = img.at<Vec3b>(i,j);
    			//递增每个灰度级的像素数
    			num0[(int)pix[0]]++;
    			num1[pix[1]]++;
    			num2[pix[2]]++;
    
    		}
    	}
    	//绘制直方图
    	//x,y,o的坐标终点
    	Point o = Point(0,800);
    	Point x = Point(500,700);
    	Point y = Point(0,0);
    
    	line(colorimg, o, y, Scalar(255, 0, 0));
    	line(colorimg, o, x, Scalar(255, 0, 0));
    
    	auto max0 = max_element(num0.begin(), num0.end());
    	auto max1 = max_element(num1.begin(), num1.end());
    	auto max2 = max_element(num2.begin(), num2.end());
    
    	int max = *max0 > *max1 ? *max0:*max1;
    	max = max > *max2 ? max : *max2;
    	cout << max<<endl;
    
    	Point p[3][256];
      //生成坐标点,并绘制
    	for (int i = 0; i < 3; i++)
    	{
    			if (i == 0)
    			{
    				for (int j = 0; j < 256; j++)
    				{
    					p[i][j].x = j*3;
    					p[i][j].y = 800 - int(num0[j] * (700.0 / max));
    				}
    				for (int j = 1; j < 256; j++)
    				{
    					line(colorimg, p[i][j - 1], p[i][j], Scalar(255, 0, 0));
    				}
    			}
    			else if (i == 1)
    			{
    				for (int j = 0; j < 256; j++)
    				{
    					p[i][j].x = j * 3;
    					p[i][j].y = 800 - int(num1[j] * (700.0 / max));
    				}
    				for (int j = 1; j < 256; j++)
    				{
    					line(colorimg, p[i][j - 1], p[i][j], Scalar(0, 255, 0));
    				}
    			}
    			else if(i==2)
    			{
    				for (int j = 0; j < 256; j++)
    				{
    					p[i][j].x = j * 3;
    					p[i][j].y = 800 - int(num2[j] * (700.0 / max));
    				}
    				for (int j = 1; j < 256; j++)
    				{
    					line(colorimg, p[i][j - 1], p[i][j], Scalar(0, 0, 255));
    				}
    			}
    	}
    
    	namedWindow("color直方图", WINDOW_AUTOSIZE);
    	imshow("color直方图", colorimg);
    
    }
    

    灰色图形直方图均衡化

    /*均衡化*/
    void mEqual()
    {
        string src = "../img/tiger.jpg";
        Mat img = imread(src, IMREAD_GRAYSCALE);
        namedWindow("oequal", WINDOW_NORMAL);
        cvResizeWindow("oequal", 480, 319);
        imshow("oequal", img);
        Mat afimg = img.clone();
        //计算图像每个灰度级的像素数
        vector<int> n(256);
        //cout << img << endl;
        for (int i = 0; i < img.rows; i++)
        {
        	//uchar* p = img.ptr<uchar>(i);
        	for (int j = 0; j < img.cols; j++)
        	{
        		int index = img.at<uchar>(i, j);
        		n[index]++;
        	}
        }
        vector<double> pr(256);
        int pix_total = img.rows*img.cols;//图形像素总数
        //归一化后,计算概率
        for (int i = 0; i < 256; i++)
        {
        	pr[i] = (float)n[i] / pix_total;
        }
        //计算skT
        vector<double> skt(256);
        for (int i = 0; i < 256; i++)
        {
        	if (i == 0)
        	{
        		skt[i] = pr[i];
        	}
        	else
        	{
        		skt[i] = skt[i-1]+pr[i];
        	}
        }
        //计算sk
        vector<int> sk(256);
        for (int i = 0; i < 256; i++)
        {
        	sk[i] = int(255*skt[i]+0.5);
        }
    
        vector < double > ps(256);
        //计算ps
        for (int i = 0; i < 256; i++)
        {
        	ps[sk[i]] += pr[i];
        }
    
        //计算均衡化后每一灰度级的像素数
        vector<int> res(256);
        for (int i = 0; i < 256; i++)
        {
        	res[i] = (int)(ps[i] * pix_total);
        	cout << res[i] << endl;
        }
        //绘制
        Mat hist = Mat::zeros(600, 800, CV_8UC3);
        auto Max = max_element(res.begin(),res.end());
        //绘制坐标系
        Point o = Point(0, 800);
        Point x = Point(500, 700);
        Point y = Point(0, 0);
    
        //x轴
        line(hist, o, x, Scalar(255, 255, 255));
        //y轴
        line(hist, o, y, Scalar(255, 255, 255));
    
        Point pts[256];//灰度点
        //生成坐标点
        for (int i = 0; i < 256; i++)
        {
        	pts[i].x = i * 3;
        	pts[i].y = 800-int(res[i] * (700.0 / *Max));
        	//cout << pts[i].x << "," << pts[i].y << "," << ps[i] << endl;
        }
        //绘制线
        for (int i = 0; i < 256; i++)
        {
        	line(hist, Point(3*i,800), pts[i], Scalar(0, 0, 205));
        }
        //均衡化后图
        for (int i = 0; i < img.rows; i++)
        {
        	for (int j = 0; j < img.cols; j++)
        	{
        		afimg.at<uchar>(i,j)=sk[img.at<uchar>(i,j)];
        	}
        }
        namedWindow("equal图", WINDOW_AUTOSIZE);
        imshow("equal图", afimg);
    
        namedWindow("equal直方图", WINDOW_AUTOSIZE);
        imshow("equal直方图", hist);
    
    }
    

    编辑日期 2019.5.16


    梦还远,路还长!
  • 相关阅读:
    调用系统相机导致照片旋转问题的修复
    JavaLearning:日期操作类
    PHP实现事件机制实例分析
    按下葫芦起了瓢
    win系统下的eclipse连接和使用linux上的hadoop集群
    利用gradle加入构建版本
    从设计到实现,一步步教你实现Android-Universal-ImageLoader-辅助类
    I帧、P帧和B帧的特点
    tcp_tw_recycle检查tcp_timestamps的内核代码
    OBS源码编译开发
  • 原文地址:https://www.cnblogs.com/qujialin/p/10877287.html
Copyright © 2011-2022 走看看