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 ...
随机推荐
- 淘宝API得到单个商品的信息,用了淘宝的SDK...
淘宝api获取到的数据.返回结果可以选择json格式和xml格式的啊.每个api下面都有sdk调用示例哦. 详细:http://wenwen.soso.com/z/q335640192.htm 淘宝开 ...
- C#程序集系列01,用记事本编写C#,IL代码,用DOS命令编译程序集,运行程序
本篇主要体验:编写C#,IL代码,用"VS2012开发人员命令提示"编译成程序集,并运行程序. □ C#文件编译为程序集 →在F盘创建as文件夹→在as文件夹下创建MyClass. ...
- Jquery焦点图/幻灯片效果 插件 KinSlideshow
JavaScript $(function(){ $("#KinSlideshow").KinSlideshow({ moveSty ...
- dao层的泛型实现(2种方法)
一: package com.wzs.test2.dao; import java.util.List; public interface CommonDAO { public <T> v ...
- 如何记录linux终端下的操作日志
如何记录linux终端下的操作日志 在linux终端下,为方便检查操作中可能出现的错误,以及避免屏幕滚屏的限制,我们可以把操作日志记录下来.常用的工具有 screen,script,以及tee等,通过 ...
- 缓存算法:LRU、LFU、FIFO
LRU全称是Least Recently Used,即最近最久未使用的意思.如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小.也就是说,当限定的空间已存满数据时,应当把最久 ...
- poj 1469 COURSES 题解
COURSES Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 21515 Accepted: 8455 Descript ...
- cocos2dxHellowoed 发现 2.2.3
cocos2d 笔记 文件夹介绍 cocosdx ----->cocos2d主要代码 CocosDenshion---->cocos2d的声音的 Document------>文档 ...
- OTL翻译(4) -- otl_stream类
otl_stream Otl_stream是具体实现otl_stream_concept的类.任何的SQL语句.SQL语句块和存储过程都能通过otl_stream进行处理. 传统的数据库API处理SQ ...
- 《Small Memory Software:Patterns For System With Limited Memory》读书笔记
原文地址:http://blog.csdn.net/jinzhuojun/article/details/13297447 虽然摩尔定律让我们的计算机硬件得以以指数速度升级,但反摩尔定律又不断消减这些 ...