• opencv实现gamma灰阶检測


    简单介绍

      本篇解说使用opencv来測试,表示camera gamma參数的灰阶卡图片指标:YA Block、DynamicRange、Gray Scale。

    详细实现

    实现代码

    #include <math.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv/cv.h>
    #include "opencv2/imgproc/imgproc.hpp"
     
    #define barPic "barPic"
    #define Pic_windosw "src"
     
    using namespace cv;
    char pic_name[20];
    char pic_tmp[20] = "tmp.jpg";
    char pic_windows[20] = "src";
    Mat src, src2;
    int src2_width = 400, src2_height = 400;
    int width, height, roi_width, roi_height;
    int rect[4];
    bool mouse_flag = false, ROI_flag = false;
    Mat imageROI;
    double white=0, black=0, graySum = 0; 
    CvFont font;    
    double hScale=1;   
    double vScale=1;    
    int lineWidth=1;
    char showWhite[20] = "White:0", showBlack[20]="Black:0", grayNumber[20]="grayNumber:0";
     
    void doGammaForA_black(Mat image){
    	int i, j, k;
    	IplImage pI_1, pI_2;
    	CvScalar s;
    	roi_width = image.rows;
    	roi_height = image.cols;
    	Mat src = Mat(roi_width, roi_height, CV_8UC1, 1);
    	white = 0;
    	black = 0;
     
    	pI_1 = image;
    	pI_2 = src;
    	cvCvtColor(&pI_1, &pI_2, CV_BGR2GRAY);
     
    	for(i=0; i<roi_width; i++){
    		for(j=0; j<10; j++){
    			s = cvGet2D(&pI_2, i, j);
    			if(white==0){
    				white = s.val[0];
    			}else{
    				white = (white + s.val[0]) / 2;	
    			}
    		}
    		for(k=roi_height-10; k< roi_height; k++){
    			s = cvGet2D(&pI_2, i, k);
    			if(black==0){
    				black = s.val[0];
    			}else{
    				black = (black + s.val[0]) / 2;	
    			}	
    		}
    	}
    	sprintf(showWhite, "White:%d", (int)white);
    	sprintf(showBlack, "Black:%d", (int)black);
    }
     
    void doGammaForGrayNumber(Mat image){
    	int i, j, k, num=0;
    	double tmp=0, cur_tmp=0;
    	IplImage pI_1, pI_2;
    	CvScalar s;
    	roi_width = image.rows;
    	roi_height = image.cols;
    	Mat src = Mat(roi_width, roi_height, CV_8UC1, 1);
    	graySum = 0;
     
    	pI_1 = image;
    	pI_2 = src;
    	cvCvtColor(&pI_1, &pI_2, CV_BGR2GRAY);
     
    	for(j=0; j<roi_height; j++){
    		for(i=0; i<roi_width; i++){
    			s = cvGet2D(&pI_2, i, j);
    			if(cur_tmp==0){
    				cur_tmp=s.val[0];
    			}else{
    				cur_tmp=(cur_tmp + s.val[0]) / 2;
    			}
    		}
    		if(num >= 3){
    			if(tmp - cur_tmp > 8){
    				graySum += 1;	
    			}
    			tmp = cur_tmp;
    			cur_tmp = 0;
    			num = 0;
    		}
    		num += 1;
    	}
    	sprintf(grayNumber, "grayNumber:%d", (int)graySum);
    }
     
    void on_mouse( int event, int x, int y, int flags, void* ustc)  {    
    	switch(event){
    		case CV_EVENT_LBUTTONDOWN:
    			mouse_flag = true;
    			rect[0] = x;
    			rect[1] = y;
    			rect[2] = 0;
    			rect[3] = 0;
    			break;
    		case CV_EVENT_LBUTTONUP:
    			src = imread(pic_name, 1);
    			mouse_flag = false;
    			rect[2] = x;
    			rect[3] = y;
    			rectangle(src, Point(rect[0], rect[1]), Point(rect[2], rect[3]), Scalar(0,255,0), 2);
    			src = imread(pic_name, 1);
    			imageROI = src(cv::Rect(rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]));
    			ROI_flag = true;
    			break;
    		case CV_EVENT_MOUSEMOVE:
    			if(mouse_flag){
    				src = imread(pic_name, 1);
    				rectangle(src, Point(rect[0], rect[1]), Point(x, y), Scalar(0,255,0), 2);
    				cv::imshow(Pic_windosw, src);
    			}
    			break;
    		default:
    			break;
    	}
    } 
     
    int main(int agrc, char* argv[]){
    	bool exit = false;
    	char c;
    	IplImage pI_barPic;
     
    	memcpy(pic_name,argv[1],sizeof(argv[1]));
     
    	src=cv::imread(pic_name,1);
    	width = src.rows;
    	height = src.cols;
    	src2 = cv::Mat(src2_width, src2_height, CV_8UC3, 1);
    	pI_barPic = src2;
    	cv::imshow(Pic_windosw, src);
     
    	cvInitFont(&font,  CV_FONT_HERSHEY_PLAIN|CV_FONT_ITALIC, hScale, vScale, 0, lineWidth);
    	cvPutText(&pI_barPic, showWhite ,cvPoint(10, 15),&font,CV_RGB(255,0,0));
    	cvPutText(&pI_barPic, showBlack ,cvPoint(10, 30),&font,CV_RGB(255,0,0));
    	cvPutText(&pI_barPic, grayNumber ,cvPoint(10,45),&font,CV_RGB(255,0,0));
    	cv::imshow(barPic, src2);
    	cvSetMouseCallback(Pic_windosw, on_mouse, NULL);
    	while(!exit){
    		c = cv::waitKey(100);
    		if(c == 'q'){
    			exit = true;	
    		}
    		if(ROI_flag){
    			cv::imshow("test", imageROI);
    			doGammaForA_black(imageROI);  //A块亮度,动态范围
    			doGammaForGrayNumber(imageROI);//Gray Scale
    			cvZero(&pI_barPic);
    			cvPutText(&pI_barPic, showWhite ,cvPoint(10, 15),&font,CV_RGB(255,0,0));
    			cvPutText(&pI_barPic, showBlack ,cvPoint(10, 30),&font,CV_RGB(255,0,0));
    			cvPutText(&pI_barPic, grayNumber ,cvPoint(10,45),&font,CV_RGB(255,0,0));
    			cv::imshow(barPic, src2);
    			ROI_flag = false;
    		}
     
    	}
    	cvDestroyAllWindows();  
     
    	return 0;  
    }

    代码解说

      1、首先也是进行各类初始化。导入了须要处理的灰阶卡照片src。生成一张空白照片src2用来显示结果。接着用cvInitFont初始化字体显示。
    依次的三个cvPutText,将YA Block、DynamicRange、Gray Scale的显示。初始化到src2相应位置。然后给src显示窗体,绑定鼠标响应函数。最后是
    一个循环,在循环中,首先等待键值,假设输入键值'q',就直接退出程序。接着推断ROI_flag是否为true,是的话就进入相应操作。不是就直接跳过。
    
    src=cv::imread(pic_name,1);
    	width = src.rows;
    	height = src.cols;
    	src2 = cv::Mat(src2_width, src2_height, CV_8UC3, 1);
    	pI_barPic = src2;
    	cv::imshow(Pic_windosw, src);
     
    	cvInitFont(&font,  CV_FONT_HERSHEY_PLAIN|CV_FONT_ITALIC, hScale, vScale, 0, lineWidth);
    	cvPutText(&pI_barPic, showWhite ,cvPoint(10, 15),&font,CV_RGB(255,0,0));
    	cvPutText(&pI_barPic, showBlack ,cvPoint(10, 30),&font,CV_RGB(255,0,0));
    	cvPutText(&pI_barPic, grayNumber ,cvPoint(10,45),&font,CV_RGB(255,0,0));
    	cv::imshow(barPic, src2);
    	cvSetMouseCallback(Pic_windosw, on_mouse, NULL);
    	while(!exit){
    		c = cv::waitKey(100);
    		if(c == 'q'){
    			exit = true;	
    		}
    		if(ROI_flag){
    		     .............
                         .............
                         .............
    		}
     
    	}
    }
      2、在鼠标响应函数中,操作非常easy,就是让用户框选中灰阶卡所在的位子。

    当用户左键按下的时候,随着鼠标的拖动,会出现一个绿色的矩形框。 当鼠标左键抬起之后,当前矩形框的位置,就被觉得是灰阶卡所在的位置。

    同一时候将标志位ROI_flag设置为true。

    void on_mouse( int event, int x, int y, int flags, void* ustc)  {    
    	switch(event){
    		case CV_EVENT_LBUTTONDOWN:
    			mouse_flag = true;
    			rect[0] = x;
    			rect[1] = y;
    			rect[2] = 0;
    			rect[3] = 0;
    			break;
    		case CV_EVENT_LBUTTONUP:
    			src = imread(pic_name, 1);
    			mouse_flag = false;
    			rect[2] = x;
    			rect[3] = y;
    			rectangle(src, Point(rect[0], rect[1]), Point(rect[2], rect[3]), Scalar(0,255,0), 2);
    			src = imread(pic_name, 1);
    			imageROI = src(cv::Rect(rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]));
    			ROI_flag = true;
    			break;
    		case CV_EVENT_MOUSEMOVE:
    			if(mouse_flag){
    				src = imread(pic_name, 1);
    				rectangle(src, Point(rect[0], rect[1]), Point(x, y), Scalar(0,255,0), 2);
    				cv::imshow(Pic_windosw, src);
    			}
    			break;
    		default:
    			break;
    	}
    }
      3、之前有提到,当ROI_flag置为true之后。就会进入相应处理函数中,首先是使用doGammaForA_black(imageROI);对框选出来的灰阶卡进行
    YA Block、DynamicRange的检測。
        检測的方式是,首先将灰阶卡图片灰阶化,然后分别取出图片最左边的10列,计算它平均亮度作为YA Block;取出图片最右边10列,也是计算它们的
    平均亮度最为最暗处亮度,当左边平均亮度减去右边平均亮度。得到的就是DynamicRange。
    
    void doGammaForA_black(Mat image){
    	int i, j, k;
    	IplImage pI_1, pI_2;
    	CvScalar s;
    	roi_width = image.rows;
    	roi_height = image.cols;
    	Mat src = Mat(roi_width, roi_height, CV_8UC1, 1);
    	white = 0;
    	black = 0;
     
    	pI_1 = image;
    	pI_2 = src;
    	cvCvtColor(&pI_1, &pI_2, CV_BGR2GRAY);
     
    	for(i=0; i<roi_width; i++){
    		for(j=0; j<10; j++){
    			s = cvGet2D(&pI_2, i, j);
    			if(white==0){
    				white = s.val[0];
    			}else{
    				white = (white + s.val[0]) / 2;	
    			}
    		}
    		for(k=roi_height-10; k< roi_height; k++){
    			s = cvGet2D(&pI_2, i, k);
    			if(black==0){
    				black = s.val[0];
    			}else{
    				black = (black + s.val[0]) / 2;	
    			}	
    		}
    	}
    	sprintf(showWhite, "White:%d", (int)white);
    	sprintf(showBlack, "Black:%d", (int)black);
    }
      4、最后是使用doGammaForGrayNumber(imageROI),进行Gray Scale的计算。计算的方式是:首先将灰阶卡图片灰阶化,然后从左往右遍历整个图片。
    以3列为一组的计算出它们的平均亮度。当相邻两块的亮度差值大于8的时候,表示Gray Scale加1.
    
    void doGammaForGrayNumber(Mat image){
    	int i, j, k, num=0;
    	double tmp=0, cur_tmp=0;
    	IplImage pI_1, pI_2;
    	CvScalar s;
    	roi_width = image.rows;
    	roi_height = image.cols;
    	Mat src = Mat(roi_width, roi_height, CV_8UC1, 1);
    	graySum = 0;
     
    	pI_1 = image;
    	pI_2 = src;
    	cvCvtColor(&pI_1, &pI_2, CV_BGR2GRAY);
     
    	for(j=0; j<roi_height; j++){
    		for(i=0; i<roi_width; i++){
    			s = cvGet2D(&pI_2, i, j);
    			if(cur_tmp==0){
    				cur_tmp=s.val[0];
    			}else{
    				cur_tmp=(cur_tmp + s.val[0]) / 2;
    			}
    		}
    		if(num >= 3){
    			if(tmp - cur_tmp > 8){
    				graySum += 1;	
    			}
    			tmp = cur_tmp;
    			cur_tmp = 0;
    			num = 0;
    		}
    		num += 1;
    	}
    	sprintf(grayNumber, "grayNumber:%d", (int)graySum);
    }

    效果演示

     相应的效果演演示样例如以下:
            
    
            
    
            
  • 相关阅读:
    基于jquery自己写滑动门(通用版)
    这一年,做为asp.net程序员我合格吗?
    基于jquery的滚动条滚动固定div(附Demo)
    asp.net获取数据随机显示(原创)
    为昨天一篇博文【asp.net,对于一个有点经验的猴子,我的要求高么?】做点解释
    2012年总结,2013年更精彩。
    放大镜
    be strong
    模拟凡客导航
    Ajax中Get请求与Post请求的区别(转载)
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/6748911.html
Copyright © 2020-2023  润新知