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 ...
随机推荐
- 利用Jenkins实现JavaWeb项目的自动化部署
修改代码,打包,上传,重启... 大把的时间花费在这些重复无味的工作上.笔者与当前主流的价值观保持一致:我们应该把时间花费在更有意义的事情上.我们可以尝试借助一些工具,让这些重复机械的工作交给计算机去 ...
- java的(PO,VO,TO,BO,DAO,POJO)解释1
java的(PO,VO,TO,BO,DAO,POJO)解释 O/R Mapping 是 Object Relational Mapping(对象关系映射)的缩写.通俗点讲,就是将对象与关系数据库绑定 ...
- 报错:无法从int?转换为int
□ 背景分析 在控制器方法中的一个参数允许为null值:public ActionResult GetByCategory(int? categoryId = null) 当把这里的categoryI ...
- 【mysql】在mysql中更新字段的部分值,更新某个字符串字段的部分内容
在mysql中更新字段的部分值,更新某个字符串字段的部分内容 sql语句如下: update goods set img = REPLACE(img,'http://ozwm3lwui.bkt.clo ...
- java获取路径(转)
1.利用System.getProperty()函数获取当前路径:System.out.println(System.getProperty("user.dir"));//user ...
- SVN中的Trunk、Tag、Brance的用法
在SVN中Branch/tag在一个功能选项中,在使用中也往往产生混淆.在实现上,branch和tag,对于svn都是使用copy实现的,所以他们在默认的权限上和一般的目录没有区别.至于何时用tag, ...
- c++模板类成员的声明和定义
c++模板类成员的声明和定义应该都放在*.h中,有普通类不一样. 如果定义放在*.cpp中,最终链接时,会报方法undefined错误. 参考:http://users.cis.fiu.edu/~we ...
- coco游戏android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := game_shared LOCAL_MODULE_FILENAME ...
- XCL-Charts画曲线图(CurveChart) 例2
还有一个横向的曲线图(CurveChart) 效果: 代码: //图基类 chart = new CurveChart(); //图所占范围大小 chart.setChartRange(0, 0, t ...
- 【UOJ Round #8】
A 一道不错的题,虽然大家都觉得是水题,然而蒟蒻我想出来的好慢……Orz alpq 发现其实就是一个网格图,每一个大块都是同一颜色……横纵坐标互不干扰…… //UOJ Round #8 A #incl ...