简单介绍
本篇解说使用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); }
效果演示
相应的效果演演示样例如以下:
时间: 2024-10-07 08:42:16