OpenCVでカメラ画像をアニメ風にする(K-meansによる減色)
この前に,OpenCVでカメラ画像をアニメ風にするプログラムを書いた.そのときは減色に量子化を用いた.
今回は,減色にK-meansを用いて,同じことをやってみた.結果は以下のようになる.
K-meansを使った方が色の数が少なくても,それなりに元の画像の雰囲気が残るのがいいところ.ただ処理が重たいため,カメラ画像をリアルタイムに処理して滑らかに再生することは難しい.
以下,コード.
main.cpp
//
// main.cpp
// videoAbstraction_Kmeans
//
// Created by 朝倉aa_debdeb on 2015/11/17.
// Copyright (c) 2015年 aa_debdeb. All rights reserved.
//
#include
#include
#include "opencv2/opencv.hpp"
cv::Mat getAnimeMat(cv::Mat img){
cv::Mat canny_img;
cv::Canny(img, canny_img, 50, 200);
const int cluster_count = 16;
cv::Mat points;
img.convertTo(points, CV_32FC3);
points = points.reshape(3, img.rows * img.cols);
cv::Mat_ clusters(points.size(), CV_32SC1);
cv::Mat centers;
cv::kmeans(points, cluster_count, clusters,
cvTermCriteria(CV_TERMCRIT_EPS|CV_TERMCRIT_ITER, 10, 1.0), 1, cv::KMEANS_PP_CENTERS, centers);
cv::Mat anime_img(img.size(), img.type());
cv::MatIterator_ itd = anime_img.begin(),
itd_end = anime_img.end();
cv::MatIterator_ canny_itd = canny_img.begin();
for(int i = 0; itd != itd_end; ++itd, ++canny_itd, ++i){
if(*canny_itd == 255){
(*itd)[0] = 0;
(*itd)[1] = 0;
(*itd)[2] = 0;
} else {
cv::Vec3f &color = centers.at(clusters(i), 0);
(*itd)[0] = cv::saturate_cast(color[0]);
(*itd)[1] = cv::saturate_cast(color[1]);
(*itd)[2] = cv::saturate_cast(color[2]);
}
}
return anime_img;
}
int main(int argc, const char * argv[]) {
// cv::Mat img = cv::imread("lenna.jpg", 1);
// if(img.empty()) return -1;
//
// cv::Mat anime_img = getAnimeMat(img);
// cv::imshow("anime image", anime_img);
// cv::waitKey(0);
cv::VideoCapture cap(0);
cv::Mat img;
while(cv::waitKey(1) != 'q'){
cap >> img;
cv::Mat anime_img = getAnimeMat(img);
cv::imshow("anime image", anime_img);
}
}
OpenCV/videoAbstraction_Kmeans at master · aa-debdeb/OpenCV