HSVに変換して色抽出する話はそこら中に転がっているのですが,
なんだかんだハマってしまったのでメモ.
http://imagingsolution.blog107.fc2.com/blog-entry-248.html
この通りやればよかったんですが,C++っぽく書き直したかったから書き直した.
コード
void colorExtraction(cv::Mat* src, cv::Mat* dst,
int code,
int ch1Lower, int ch1Upper,
int ch2Lower, int ch2Upper,
int ch3Lower, int ch3Upper
)
{
cv::Mat colorImage;
int lower[3];
int upper[3];
cv::Mat lut = cv::Mat(256, 1, CV_8UC3);
cv::cvtColor(*src, colorImage, code);
lower[0] = ch1Lower;
lower[1] = ch2Lower;
lower[2] = ch3Lower;
upper[0] = ch1Upper;
upper[1] = ch2Upper;
upper[2] = ch3Upper;
for (int i = 0; i < 256; i++){
for (int k = 0; k < 3; k++){
if (lower[k] <= upper[k]){
if ((lower[k] <= i) && (i <= upper[k])){
lut.data[i*lut.step+k] = 255;
}else{
lut.data[i*lut.step+k] = 0;
}
}else{
if ((i <= upper[k]) || (lower[k] <= i)){
lut.data[i*lut.step+k] = 255;
}else{
lut.data[i*lut.step+k] = 0;
}
}
}
}
//LUTを使用して二値化
cv::LUT(colorImage, lut, colorImage);
//Channel毎に分解
std::vector<cv::Mat> planes;
cv::split(colorImage, planes);
//マスクを作成
cv::Mat maskImage;
cv::bitwise_and(planes[0], planes[1], maskImage);
cv::bitwise_and(maskImage, planes[2], maskImage);
//出力
cv::Mat maskedImage;
src->copyTo(maskedImage, maskImage);
*dst = maskedImage;
}
ハマりどころ
LUT
LUT(ルックアップテーブル)の作成がうまくいってなかった.
3chのLUTを生成するとき,3次元の配列を突っ込むのではなくて3倍?でかい配列にする必要がありました.
ダメな例
int lut[256][3];
for(int i = 0; i < 256; i++){
for(int k = 0; k < 3; k++){
lut[i][k] = ...
}
}
cv::Mat lutMat = cv::Mat( 256, 1, CV_8UC3, lut );
//うまくいかない
cv::LUT(src, lutMat, dst);
画像のマスク
cv::MatのcopyTo(dst, mask)は,どうやらdstに非ゼロの値が入っているとマスクされないようで,
まずdstをゼロで埋める必要があるっぽいです.
今回は新しくcv::Matを用意してやりました.
実行例
適当なカラー画像を用意します.
色抽出するときはRGBで範囲を指定するよりもHSVの方が適しているので,
RGBをHSVに変換してから色を抽出します.
OpenCVでは,H,S,Vを以下の範囲で指定してやります.
H:色相 0~180
S:彩度 0~255
V:明度 0~255
cv::Mat origImage; //適当に画像を突っ込む
cv::Mat extractedImage;
//H:150-165, S:100-255, V:70-255
colorExtraction(&origImage, &extracted, CV_BGR2HSV, 150, 165, 100, 255, 70, 255);
背景が少し残ってしまいましたが概ね綺麗に抽出できてます.
参考
http://imagingsolution.blog107.fc2.com/blog-entry-248.html
http://docs.opencv.org/modules/core/doc/operations_on_arrays.html
http://www.me.sie.dendai.ac.jp/labWiki/wiki.cgi?page=%B3%AC%C4%B4%CA%D1%B4%B9