請先參考下面這一篇, 篩選RGB得到顏色範圍內的遮罩
RGB顏色範圍內的遮罩應用 Part II
----------------------------------------------------
先來認識inRange函式定義
inRange
Checks if array elements lie between the elements of two other arrays.
- C++: void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst)
- Python: cv2.inRange(src, lowerb, upperb[, dst]) → dst
- C: void cvInRange(const CvArr* src, const CvArr* lower, const CvArr* upper, CvArr* dst)
- C: void cvInRangeS(const CvArr* src, CvScalar lower, CvScalar upper, CvArr* dst)
- Python: cv.InRange(src, lower, upper, dst) → None
- Python: cv.InRangeS(src, lower, upper, dst) → None
Parameters:
- src – first input array.
- lowerb – inclusive lower boundary array or a scalar.
- upperb – inclusive upper boundary array or a scalar.
- dst – output array of the same size as src and CV_8U type.
The function checks the range as follows:
For every element of a single-channel input array:
For two-channel arrays:
and so forth.
That is, dst (I) is set to 255 (all 1 -bits) if src (I) is within the specified 1D, 2D, 3D, ... box and 0 otherwise.
When the lower and/or upper boundary parameters are scalars, the indexes (I) at lowerb and upperb in the above formulas should be omitted.
----------------------------------------------------
接下來, RGB2HSV
colorInRange.h
colorInRange.cpp
void ImgProc::RGB2HSV()
{
Mat dst = RGB2HSV(m_src);
namedWindow("HSV", CV_WINDOW_NORMAL);
cv::imshow("HSV", dst);
}
Mat ImgProc::RGB2HSV(const Mat& src)
{
assert(src.type() == CV_8UC3);
Mat dst;
cv::cvtColor(src, dst, CV_BGR2HSV);
return dst;
}
Form1.cs
private void rGB2HSVToolStripMenuItem_Click(object sender, EventArgs e)
{
m_ip.RGB2HSV();
}
測試RGB2HSV
--------------------------------------------------------
接下來, 測試BGR抽離
colorInRange.h
colorInRange.cpp
void ImgProc::splitColorBGR()
{
vector<Mat> spl = splitColor(m_src);
namedWindow("spl1", CV_WINDOW_NORMAL);
namedWindow("spl2", CV_WINDOW_NORMAL);
namedWindow("spl3", CV_WINDOW_NORMAL);
cv::imshow("spl1", spl[0]); //b
cv::imshow("spl2", spl[1]); //g
cv::imshow("spl3", spl[2]); //r
}
vector<Mat> ImgProc::splitColor(const Mat& src)
{
vector<Mat> dst;
cv::split(src, dst);
return dst;
}
Form1.cs
private void splitRGBToolStripMenuItem_Click(object sender, EventArgs e)
{
m_ip.splitColorBGR();
}
測試結果1 (BGR抽離)
測試結果2 (BGR抽離)
--------------------------------------------------------
接下來, 要測試輸出R,G,B三個矩陣的像素值到一個或三個txt檔案[5]
colorInRange.h
colorInRange.cpp
// 輸出RGB像素
void ImgProc::outputTxtRGB(wchar_t* fileRed, wchar_t* fileGreen, wchar_t* fileBlue)
{
wstring wsR(fileRed);
wstring wsG(fileGreen);
wstring wsB(fileBlue);
string nameR = ImgProc::WstringToString(wsR);
string nameG = ImgProc::WstringToString(wsG);
string nameB = ImgProc::WstringToString(wsB);
outputTxtRGB(m_src, nameR.c_str(), nameG.c_str(), nameB.c_str() );
//cv::FileStorage file(name.c_str(), cv::FileStorage::WRITE);
//file << m_src;
}
void ImgProc::outputTxtRGB(const Mat& src, const char* fileRed, const char* fileGreen, const char* fileBlue)
{
ofstream foutRed, foutGreen, foutBlue;
foutRed.open(fileRed, std::ios_base::out);
foutGreen.open(fileGreen, std::ios_base::out);
foutBlue.open(fileBlue, std::ios_base::out);
if (!foutRed)
return;
if (!foutGreen)
return;
if (!foutBlue)
return;
for (int i = 0; i< src.rows; i++)
{
for (int j = 0; j<src.cols; j++)
{
foutBlue << setw(3) << (int)src.at<cv::Vec3b>(i, j)[0] << " ";
foutGreen << setw(3) << (int)src.at<cv::Vec3b>(i, j)[1] << " ";
foutRed << setw(3) << (int)src.at<cv::Vec3b>(i, j)[2] << " ";
}
foutBlue << endl;
foutGreen << endl;
foutRed << endl;
}
foutBlue.close();
foutGreen.close();
foutRed.close();
}
Form1.cs
private void outputRGBTextFileToolStripMenuItem_Click(object sender, EventArgs e)
{
using (SaveFileDialog sfdR = new SaveFileDialog())
using (SaveFileDialog sfdG = new SaveFileDialog())
using (SaveFileDialog sfdB = new SaveFileDialog())
{
sfdR.Filter = "Text File|*.txt|Csv File|*.csv";
sfdR.Title = "輸出Red純文字檔案";
sfdG.Filter = "Text File|*.txt|Csv File|*.csv";
sfdG.Title = "輸出Green純文字檔案";
sfdB.Filter = "Text File|*.txt|Csv File|*.csv";
sfdB.Title = "輸出Blue純文字檔案";
if (sfdR.ShowDialog() == System.Windows.Forms.DialogResult.OK &
sfdG.ShowDialog() == System.Windows.Forms.DialogResult.OK &
sfdB.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
unsafe
{
fixed (char* fileR = sfdR.FileName)
fixed (char* fileG = sfdG.FileName)
fixed (char* fileB = sfdB.FileName)
{
m_ip.outputTxtRGB(fileR, fileG, fileB);
}
}
}
}
}
Red channel
Green channel
Blue channel
MATLAB驗證
--------------------------------------------------------
接下來, 測試HSV抽離出來並輸出純文字檔案[7]
Different applications use different scales for HSV. For example gimp uses H = 0-360, S = 0-100 and V = 0-100
. But OpenCV uses H: 0 - 180, S: 0 - 255, V: 0 - 255
以下為wiki HSL和HSV幾何示意圖[8]
H channel
MATLAB驗證
S channel
MATLAB驗證
V channel
MATLAB驗證
--------------------------------------------------------
所以, 接下來可以套用在HSV顏色範圍內的遮罩
colorInRange.h
#include <wchar.h>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <fstream>
#include <iomanip>
#pragma once
using namespace std;
using namespace cv;
namespace CVision
{
public ref class ImgProc
{
public:
void runColorInRangeHSV(double minH, double maxH, double minS, double maxS, double minV, double maxV); // 執行HSV顏色範圍內像素
void outputTxtHSV(wchar_t* fileH, wchar_t* fileS, wchar_t* fileV); // 輸出HSV像素
void outputTxtRGB(wchar_t* fileRed, wchar_t* fileGreen, wchar_t* fileBlue); // 輸出RGB像素
void splitColorBGR();
void RGB2HSV();
void runColorInRangeRGB(UINT minR, UINT maxR, UINT minG, UINT maxG, UINT minB, UINT maxB); // 執行RGB顏色範圍內像素
bool imread(wchar_t* filename);
bool imshow();
ImgProc();
~ImgProc();
private:
Mat colorInRangeHSV(const Mat& src, double minH, double maxH, double minS, double maxS, double minV, double maxV); // 篩選HSV顏色範圍內像素
void outputTxtHSV(const Mat& src, const char* fileH, const char* fileS, const char* fileV); // 輸出HSV像素
void outputTxtRGB(const Mat& src, const char* fileRed, const char* fileGreen, const char* fileBlue); // 輸出RGB像素
vector<Mat> splitColor(const Mat& src);
Mat RGB2HSV(const Mat& src);
Mat colorInRangeRGB(const Mat& src, UINT minR, UINT maxR, UINT minG, UINT maxG, UINT minB, UINT maxB); // 篩選RGB顏色範圍內像素
std::string WstringToString(const std::wstring str);
};
ImgProc::ImgProc()
{
}
ImgProc::~ImgProc()
{
}
}
colorInRange.cpp
// 執行HSV顏色範圍內像素
void ImgProc::runColorInRangeHSV(double minH, double maxH, double minS, double maxS, double minV, double maxV)
{
Mat dst;
Mat mask;
cvtColor(m_src, dst, CV_BGR2HSV);
mask = colorInRangeHSV(dst, minH, maxH, minS, maxS, minV, maxV);
if (!mask.data)
return;
// Show source image
namedWindow("color in range of HSV", CV_WINDOW_NORMAL);
cv::imshow("color in range of HSV", mask);
}
// 篩選HSV顏色範圍內像素
Mat ImgProc::colorInRangeHSV(const Mat& src, double minH, double maxH, double minS, double maxS, double minV, double maxV)
{
assert(src.type() == CV_8UC3);
Mat mask;
//inRange(src, Scalar(minH, minS, minV), Scalar(maxH, maxS, maxV), mask);
inRange(src, Scalar_<double>(minH, minS, minV), Scalar_<double>(maxH, maxS, maxV), mask);
return mask;
}
Video 2016 03 31 143650 HSV animation
參考資料
1. RGB顏色範圍內的遮罩應用 Part I: Visual Studio 2013編譯環境建構
3. Quick Installation for OpenCV 2.4.10 with Visual Studio 2013
4. i want to split and show R B G pictures ,why does it not work?
5. How to write a Float Mat to a file in OpenCV
7. Choosing correct HSV values for OpenCV thresholding with InRangeS
8. HSL和HSV色彩空間
9. Changing Colorspaces Object Tracking
留言列表