Opencv计算机视觉编程攻略-第三节 图像颜色处理
第三节 图像颜色处理
- 1.颜色比较
- 2.GrabCut分割图像
- 3.色调、饱和度以及亮度
1.颜色比较
主要实现逐像素的颜色比较,其中注意BGR颜色空间不连续,不利于颜色提取和区分,转换到Lab空间:
int getColorDistance(const cv::Vec3b& color1, const cv::Vec3b& color2) const {
// 方法一
return abs(color1[0]-color2[0])+
abs(color1[1]-color2[1])+
abs(color1[2]-color2[2]);
// 方法二
return static_cast<int>(cv::norm<int,3>(cv::Vec3i(color[0]-color2[0],color[1]-color2[1],color[2]-color2[2])));
// 方法三 直接使用函数
cv::Vec3b dist;
cv::absdiff(color,color2,dist);
return cv::sum(dist)[0];
}
// 使用指针遍历图像进行颜色比较
Mat process(const Mat &image) {
// same size as input image, but 1-channel
result.create(image.size(),CV_8U);
// Converting to Lab color space
if (useLab)
cv::cvtColor(image, converted, cv::COLOR_BGR2Lab);
// get the iterators
Mat_<cv::Vec3b>::const_iterator it= image.begin<Vec3b>();
Mat_<cv::Vec3b>::const_iterator itend= image.end<Vec3b>();
Mat_<uchar>::iterator itout= result.begin<uchar>();
// get the iterators of the converted image
if (useLab) {
it = converted.begin<cv::Vec3b>();
itend = converted.end<cv::Vec3b>();
}
// 指针遍历
for ( ; it!= itend; ++it, ++itout) {
// compute distance from target color
if (getDistanceToTargetColor(*it)<maxDist) {
*itout= 255;
} else {
*itout= 0;
}
// end of pixel processing ----------------
}
return result;
}
2.GrabCut分割图像
floodFill函数,支持用户选择种子点,opencv依据差异值进行快速处理,比如office中的设置透明色,就类似于该算法的实现
// testing floodfill
cv::floodFill(image, // input/ouput image
cv::Point(100, 50), // seed point
cv::Scalar(255, 255, 255), // repainted color(0,0,0)则是黑色
(cv::Rect*)0, // bounding rectangle of the repainted pixel set
cv::Scalar(35, 35, 35), // low and high difference threshold
cv::Scalar(35, 35, 35), // most of the time will be identical
cv::FLOODFILL_FIXED_RANGE); // pixels are compared to seed color
cv::namedWindow("Flood Fill result");
result = colordetector(image);
GrabCut分割图像通过用户标记前景框,算法为2004年提出,主要是将图像依据颜色相似进行图块分割,然后再使用边缘特征进一步分割,将问题转化为连通图的合并问题,最后以四种类型作为结果输出
// define bounding rectangle
cv::Rect rectangle(50,25,210,180);
// the models (internally used)
cv::Mat bgModel,fgModel;
// segmentation result
cv::Mat result; // segmentation (4 possible values)
// GrabCut segmentation
cv::grabCut(image, // input image
result, // segmentation result
rectangle,// rectangle containing foreground
bgModel, fgModel, // models
5, // number of iterations
cv::GC_INIT_WITH_RECT); // use rectangle
// Get the pixels marked as likely foreground GC_PR_FGD有四种不同分类结果
cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);
// or:
// result= result&1;
两种方法对比图下,GrabCut能够有效保留前景要素边缘特征
最终基于边框提取前景要素:
3.色调、饱和度以及亮度
将图像转换到连续空间Lab进行处理往往可以获得更为连续的结果,而HSV颜色表示更加符合人类视觉感知
cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV);
cv::cvtColor(hsv,newImage, cv::COLOR_HSV2BGR);
cv::cvtColor(image,brightness, cv::COLOR_Lab2BGR);
void detectHScolor(const cv::Mat& image, // input image
double minHue, double maxHue, // Hue interval
double minSat, double maxSat, // saturation interval
cv::Mat& mask) { // output mask
// convert into HSV space
cv::Mat hsv;
cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV);
// split the 3 channels into 3 images
std::vector<cv::Mat> channels;
cv::split(hsv, channels);
// channels[0] is the Hue
// channels[1] is the Saturation
// channels[2] is the Value
// Hue masking
cv::Mat mask1; // below maxHue
cv::threshold(channels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV);
cv::Mat mask2; // over minHue
cv::threshold(channels[0], mask2, minHue, 255, cv::THRESH_BINARY);
cv::Mat hueMask; // hue mask
if (minHue < maxHue)
hueMask = mask1 & mask2;
else // if interval crosses the zero-degree axis
hueMask = mask1 | mask2;
// Saturation masking
// below maxSat
cv::threshold(channels[1], mask1, maxSat, 255, cv::THRESH_BINARY_INV);
// over minSat
cv::threshold(channels[1], mask2, minSat, 255, cv::THRESH_BINARY);
cv::Mat satMask; // saturation mask
satMask = mask1 & mask2;
// combined mask
mask = hueMask&satMask;
}
诸如人体皮肤再HSV颜色域中具有显著的特征
该节相关代码已上传到个人文档,按需下载链接: 点击下载