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);
- }
效果演示
- 相应的效果演演示样例如以下:
- watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTYzMDQ1OA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
opencv实现gamma灰阶检測的更多相关文章
- 利用opencv中的级联分类器进行人脸检測-opencv学习(1)
OpenCV支持的目标检測的方法是利用样本的Haar特征进行的分类器训练,得到的级联boosted分类器(Cascade Classification).注意,新版本号的C++接口除了Haar特征以外 ...
- C++开发人脸性别识别教程(10)——加入图片的人脸检測程序
现在我们的MFC框架已经初具规模,能够读取并显示目录下的图片.在这篇博文中我们将向当中加入人脸检測的程序. 一.人脸检測算法 这里我们使用OpenCv封装的Adaboost方法来进行人脸检測,參见:C ...
- 【从零学习openCV】IOS7下的人脸检測
前言: 人脸检測与识别一直是计算机视觉领域一大热门研究方向,并且也从安全监控等工业级的应用扩展到了手机移动端的app,总之随着人脸识别技术获得突破,其应用前景和市场价值都是不可估量的,眼下在学习ope ...
- 【OpenCV新手教程之十二】OpenCV边缘检測:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/25560901 作者:毛星云(浅墨) ...
- 基于QT和OpenCV的人脸检測识别系统(2)
紧接着上一篇博客的讲 第二步是识别部分 人脸识别 把上一阶段检測处理得到的人脸图像与数据库中的已知 人脸进行比对,判定人脸相应的人是谁(此处以白色文本显示). 人脸预处理 如今你已经得到一张人脸,你能 ...
- 【OpenCV新手教程之十七】OpenCV重映射 & SURF特征点检測合辑
本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/30974513 作者:毛星云(浅墨) ...
- 图像边缘检測--OpenCV之cvCanny函数
图像边缘检測--OpenCV之cvCanny函数 分类: C/C++ void cvCanny( const CvArr* image, CvArr* edges, double threshold1 ...
- Python下opencv使用笔记(七)(图像梯度与边缘检測)
梯度简单来说就是求导,在图像上表现出来的就是提取图像的边缘(无论是横向的.纵向的.斜方向的等等),所须要的无非也是一个核模板.模板的不同结果也不同.所以能够看到,全部的这些个算子函数,归结究竟都能够用 ...
- opencv对图像进行边缘及角点检測
opencv对图像进行边缘及角点检測 先看结果: 代码: // ConsoleApplication1_812.cpp : Defines the entry point for the consol ...
随机推荐
- sql 递归查询所有的下级
--> 生成测试数据表: [tb] IF OBJECT_ID('[Users]') IS NOT NULL DROP TABLE [Users] GO CREATE TABLE [Use ...
- java开发C语言编译器
http://study.163.com/course/introduction.htm?courseId=1003169025 http://study.163.com/course/courseM ...
- 将数据处理逻辑集中到一处进行管理,逐步实现真正有效的 MVC 分层结构
将数据处理逻辑集中到一处进行管理,逐步实现真正有效的 MVC 分层结构.
- 解决Ubuntu下的Eclipse打开Windows编写的java代码的中文乱码
其实所有的中文乱码 问题都是编码不同所导致的.这里要想让eclipse能正常显示出汉字,就要修改它的字符编码 步骤如下: 1 ,点击菜单栏中的Window(窗口),选择Preferences(首选项) ...
- uva 10160 Servicing Stations(DFS+剪枝)
Servicing stations A company offers personal computers for sale in N towns (3 <= N <= 35). The ...
- go语言之进阶篇面向对象编程
1.面向对象编程 对于面向对象编程的支持Go 语言设计得非常简洁而优雅.因为, Go语言并没有沿袭传统面向对象编程中的诸多概念,比如继承(不支持继承,尽管匿名字段的内存布局和行为类似继承,但它并不是继 ...
- C#读写txt文件的两种方法介绍[转]
C#读写txt文件的两种方法介绍 1.添加命名空间 System.IO; System.Text; 2.文件的读取 (1).使用FileStream类进行文件的读取,并将它转换成char数组,然后输出 ...
- NGUI诡异的drawCall
看了很多关于NGUI drawCall的文章,见得比较多的一个观点是:一个 Atlas 对应一个Drawcall. 好奇心下做了个demo,两个panel中只用到一个Atlas,却产生了10个draw ...
- (转)Unity3D Android手机开发环境配置,可真机发布调试
此方法配置好,在可以在unity直接发布到手机上,并可以实时调试. 1.配置eclipse环境:首先在官网下载安装包:http://developer.android.com/sdk/index.ht ...
- new/malloc的差别
1. malloc()函数 1.1 malloc的全称是memory allocation.中文叫动态内存分配. 原型:extern void *malloc(unsigned int num_byt ...