opencv实战3-处理图像的颜色

1 处理图像的颜色

1.1 提取指定的颜色区域

cv::floodFill() 函数

1.2 分割图像

cv::grabCut()函数,用于从静态图像中提取前景物体。

1.3 转换颜色的表示方法

HSV:色调、饱和度、亮度的 色彩空间。

色调(hue):表示主色;

饱和度(saturation):表示颜色的鲜艳程度,柔和的颜色饱和度较低。

亮度(brightness):表示某种颜色的光亮程度。

在图像处理中使用较多的是 HSV 颜色空间,它比 RGB 更接近人们对彩色的感知经验。非常直观地表达颜色的色调、鲜艳程度和明暗程度,方便进行颜色的对比。

组成:

  • Hue(色调、色相)
  • Saturation(饱和度、色彩纯净度)
  • Value(明度)

圆柱体来表示 HSV 颜色空间,圆柱体的横截面可以看做是一个极坐标系 ,H 用极坐标的极角表示,S 用极坐标的极轴长度表示,V 用圆柱中轴的高度表示。

 Hue 用角度度量,取值范围为0~360°,表示色彩信息,即所处的光谱颜色的位置。

 颜色圆环上所有的颜色都是光谱上的颜色,从红色开始按逆时针方向旋转,Hue=0 表示红色,Hue=120 表示绿色,Hue=240 表示蓝色等等。

其中水平方向表示饱和度,饱和度表示颜色接近光谱色的程度。饱和度越高,说明颜色越深,越接近光谱色饱和度越低,说明颜色越浅,越接近白色。饱和度为0表示纯白色。取值范围为0~100%,值越大,颜色越饱和。

竖直方向表示明度,决定颜色空间中颜色的明暗程度,明度越高,表示颜色越明亮,范围是 0-100%。明度为0表示纯黑色(此时颜色最暗)。

1.4 通过颜色实现肤色识别

HSV 常用于搜索特性颜色的物体。如使用颜色用于检测肤色:HSV是一种将RGB色彩空间中的点在倒圆锥体中的表示方法,其包含色相(H)、饱和度(S)、名度(V)三个基本属性。在HSV颜色空间中,一般通过色相值对肤色区域进行筛选:2<H<13。


#include <iostream>
#include <opencv2/opencv.hpp>
#include  <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
void hand_HSV(const cv::Mat& frame,  //输入图像
    double minHue, double maxHue,    //色调区间
    double minSat, double maxSat,    //饱和度区间
    cv::Mat& mask)        //输出掩码
{
    //图像转换到HSV空间
    cv::Mat frameHSV;
    cv::cvtColor(frame, frameHSV, COLOR_BGR2HSV);//在opencv中,其默认的颜色制式排列是BGR而非RGB
//将3个通道分割到3副图像中
    std::vector<cv::Mat> HSVchannels;
    cv::split(frameHSV, HSVchannels);//分离后, channels[0]对应H, channels[1]对应S, channels[2]对应
//色调掩码
    cv::Mat mask1;
    cv::threshold(HSVchannels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV);
    cv::Mat mask2;
    cv::threshold(HSVchannels[0], mask2, minHue, 255, cv::THRESH_BINARY_INV);
    cv::Mat hueMask;
    if (minHue < maxHue)
        hueMask = mask1 & mask2;
    else
        hueMask = mask1 | mask2;
    //饱和度掩码
    cv::Mat satMask;
    cv::inRange(HSVchannels[1], minSat, maxSat, satMask);
    //组合掩码
    mask = hueMask & satMask;

};

//检测肤色
cv::Mat mask;
hand_HSV(image,160,10,25,166,mask);
//显示使用掩码后的图像
cv::Mat detected(image.size(),CV_8UC3,cv::Scalar(0,0,0));
image.copyTo(detected,mask);

1.5 图像掩码

使用opencv通过掩码去扣取图像中感兴趣的区域。

1、读取一张图片

2、转换颜色格式为hsv

3、设置要扣取区域颜色的上下门限

4、从原始图像中获取感兴趣区域的掩码

5、使用掩码和原始图像做与运算得到最后感兴趣区域的图像

#读取一张图片
img = cv2.imread('hat.jpg',cv2.IMREAD_COLOR)
#转换为HSV
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
#设置红色的上下门限
dark_yellow = numpy.array([60,150,70])
light_yellow = numpy.array([255,255,255])
#掩膜
mask = cv2.inRange(hsv,dark_yellow,light_yellow)
#与运算
res = cv2.bitwise_and(img,img,mask=mask)
 
#显示图片
cv2.imshow('original',img)
cv2.imshow('mask',mask)
cv2.imshow('result',res)

2 直方图统计像素

2.1 计算图像直方图

直方图 是一个简单的表格,表示一副图像中具有某个值的像素数量。如灰度图像中的直方图有256个项目,也叫箱子,0号箱子提供值为0的像素的数量,依次类推。

计算图像直方图

 cv::calcHist 函数

void calcHist(const Mat*images, // 源图像
int nimages, // 源图像的个数(通常为 1)
const int*channels, // 列出通道
InputArray mask, // 输入掩码(需处理的像素)
OutputArray hist, // 输出直方图
int dims, // 直方图的维度(通道数量)
const int*histSize, // 每个维度位数
const float**ranges, // 每个维度的范围
bool uniform=true, // true 表示箱子间距相同
bool accumulate=false) // 是否在多次调用时进行累加

(1)计算单色图像直方图

// 创建灰度图像的直方图
class Histogram1D {
private:
    int histSize[1]; // 直方图中箱子的数量
    float hranges[2]; // 值范围
    const float* ranges[1]; // 值范围的指针
    int channels[1]; // 要检查的通道数量
public:
    Histogram1D() {
    // 准备一维直方图的默认参数
        histSize[0]= 256; // 256个箱子
        hranges[0]= 0.0; // 从 0开始(含)
        hranges[1]= 256.0; // 到 256(不含)
        ranges[0]= hranges;
        channels[0]= 0; // 先关注通道 0
    }

    // 计算一维直方图
    cv::Mat getHistogram(const cv::Mat &image)
 {
        cv::Mat hist;

        // 用 calcHist 函数计算一维直方图
        cv::calcHist(&image, 1, // 仅为一幅图像的直方图
        channels, // 使用的通道
        cv::Mat(), // 不使用掩码
        hist, // 作为结果的直方图
        1, // 这是一维的直方图
        histSize, // 箱子数量
        ranges // 像素值的范围
        );
        return hist;
    }
}

// 读取输入的图像
cv::Mat image= cv::imread("group.jpg", 0); // 以黑白方式打开
// 直方图对象
Histogram1D h;
// 计算直方图
cv::Mat histo= h.getHistogram(image);


//显示直方图
// 创建一个表示直方图的图像(静态方法)
static cv::Mat getImageOfHistogram (const cv::Mat &hist, int zoom) {
// 取得箱子值的最大值和最小值
    double maxVal = 0;
    double minVal = 0;
    cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0);

    // 取得直方图的大小
    int histSize = hist.rows;
    // 用于显示直方图的方形图像
    cv::Mat histImg(histSize*zoom, histSize*zoom,
    CV_8U, cv::Scalar(255));

    // 设置最高点为 90%(即图像高度)的箱子个数
    int hpt = static_cast<int>(0.9*histSize);
    // 为每个箱子画垂直线
    for (int h = 0; h < histSize; h++) {
    float binVal = hist.at<float>(h);
    if (binVal>0) {
        int intensity = static_cast<int>(binVal*hpt / maxVal);
        cv::line(histImg, cv::Point(h*zoom, histSize*zoom),
        cv::Point(h*zoom, (histSize - intensity)*zoom),
        cv::Scalar(0), zoom);
    }
    }
    return histImg;
}
int zoom=1;

cv::Mat histImage = getImageOfHistogram(hist, zoom);


对直方图后的图像做与之处理:

cv::Mat thresholded; // 输出二值图像
cv::threshold(image,thresholded,70, // 阈值
255, // 对超过阈值的像素赋值
cv::THRESH_BINARY); // 阈值化类型

计算彩色图像直方图

class ColorHistogram {
private:
int histSize[3]; // 每个维度的大小
float hranges[2]; // 值的范围(三个维度用同一个值)
const float* ranges[3]; // 每个维度的范围
int channels[3]; // 需要处理的通道
public:
ColorHistogram() {
    // 准备用于彩色图像的默认参数
    // 每个维度的大小和范围是相等的
        histSize[0]= histSize[1]= histSize[2]= 256;
        hranges[0]= 0.0; // BGR 范围为 0~256
        hranges[1]= 256.0;
        ranges[0]= hranges; // 这个类中
        ranges[1]= hranges; // 所有通道的范围都相等
        ranges[2]= hranges;
        channels[0]= 0; // 三个通道:B
        channels[1]= 1; // G
        channels[2]= 2; // R
    }
// 计算直方图
cv::Mat getHistogram(const cv::Mat &image) {
    cv::Mat hist;
    // 计算直方图
    cv::calcHist(&image, 1, // 单幅图像的直方图
    channels, // 用到的通道
    cv::Mat(), // 不使用掩码
    hist, // 得到的直方图
    3, // 这是一个三维直方图
    histSize, // 箱子数量
    ranges // 像素值的范围
    );
    return hist;
    }
}

2.2 直方图应用

2.2.1 增强图像对比度

        通过伸展直方图,使它布满可用强度值得全部范围,可有效提高图像质量。

2.2.2 直方图均衡化

        原始图像由于其灰度分布可能集中在较窄的区间,造成图像不够清晰。例如,过曝光图像的灰度级集中在高亮度范围内,而曝光不足将使图像灰度级集中在低亮度范围内。采用直方图均衡化,可以把原始图像的直方图变换为均匀分布(均衡)的形式,这样就增加了像素之间灰度值差别的动态范围,从而达到增强图像整体对比度的效果。

直方图均衡化的基本原理是:对在图像中像素个数多的灰度值(即对画面起主要作用的灰度值)进行展宽,而对像素个数少的灰度值(即对画面不起主要作用的灰度值)进行归并,从而增大对比度,使图像清晰,达到增强的目的。

参考文献:

【1】【图像处理算法】直方图均衡化:【图像处理算法】直方图均衡化_GQ-CSDN博客_直方图均衡化

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值