巷で大人気の漫画カメラというソフトがあります。

漫画カメラ | スマートフォン カメラアプリ | スーパーソフトウエア



その漫画カメラの実装について、こちらにわかりやすい解説を見つけました。

【連載】コンピュータビジョンのセカイ - 今そこにあるミライ (39) iPhoneアプリ「漫画カメラ」に見るコンピュータビジョンの実応用例 | 開発・SE | マイナビニュース

【連載】コンピュータビジョンのセカイ - 今そこにあるミライ (40) iPhoneアプリ「漫画カメラ」で使われている画像処理手法その1 | 開発・SE | マイナビニュース

【連載】コンピュータビジョンのセカイ - 今そこにあるミライ (41) iPhoneアプリ「漫画カメラ」で使われている画像処理手法その2 | 開発・SE | マイナビニュース



こちらで具体的に、iOSで実装されている方がおります。

OpenCVで写真を漫画風に加工しよう 〜実装編〜 | Developers.IO



ソース

ということで、今回は漫画カメラ風の画像を作り出すのをやってみました。
ちなみに、PythonとOpenCVで実装しています。
手順は以下の通りです。
  1. 画像を読み込む
  2. Cannyのエッジ検出を行い、その画像をネガポジ変換を行う。
  3. 3値化処理を行う
  4. 3値化処理の灰色に割り当てられたところをスクリーントーンに置き換える
  5. 2,4の画像を合成する


ちなみに、2,3をいっぺんに行ったり、
5の合成の後に灰色部分を消すため再度2値化処理を行ったり色々とアレ・・・です。。。


スクリーントーンはこちらのサイトからいただいたものを使用しました。
WEB用無料素材 | デジタルトーンスジタオ




import cv2
import numpy

# 画像を読み込む
img = cv2.imread("Lenna.bmp",cv2.CV_LOAD_IMAGE_GRAYSCALE)
screen = cv2.imread("screen.bmp",cv2.CV_LOAD_IMAGE_GRAYSCALE)

# エッジ検出後にネガポジ反転
edge= cv2.Canny(img,80,120)
nega = cv2.bitwise_not(edge)

# sizeを取得
width = img.shape[0] 
height = img.shape[1]

# 3値化を行う(ただし灰色の場合はスクリーントーンに置き換える)
temp = numpy.zeros_like(img)
for i in xrange(width):
    for j in xrange(height):
        if img[i,j]<80:
            temp[i,j] = 0
        elif img[i,j]>=80 and img[i,j]<160:
            temp[i,j] = screen[i,j]
        else:
            temp[i,j] = 255

# 3値化とエッジの画像を合成
alpha = 0.5
result = cv2.addWeighted(nega,alpha,temp,1-alpha,0.0)
(thresh,result)=cv2.threshold(result,200,255,cv2.THRESH_BINARY)



結果

結果は以下になります。。。


【元画像】
Lenna



【エッジ画像(Canny)】
edge.png



【ネガポジ変換後】
nega.png



【3値化画像】
3val.png



【ネガポジ+3値化=漫画風】
result_20130320013925.png



反省点

画像の大きさに合わせてスクリーントンのサイズを変えたり、
スクリーントンのパターンを変更できるようにしたいですね。

あとは、画像合成のうまい方法忘れてしまいました。。。orz

お久しぶりです。
今回は普通(?)のOpencvとPythonです。
#OpenCVSharpとの兼ね合いのため、私の環境のOpenCVのバージョンが2.4.0となっておりますので、ご注意願いますm(_ _)m



導入

OpenCVはインストールされていると仮定してですが、
Pythonで動かすにはもう一手間必要です。

C:\opencv\build\python\2.7 にある
cv2.pyd というファイルを下記のフォルダにコピーします。

C:\Python27\Lib\site-packages
#フォルダ名などの違いは各自のフォルダに読み替えて実行願います。



ソース

SURFの実行方法を調べていたところ、下記サイトで相談&回答されています。


How to visualize descriptor matching using opencv module in python - Stack Overflow

ただ、このまま実行したところ、エラーが生じたため。その部分(65行目)を修正しました。
# matching features of two images
import cv2
import sys
import scipy as sp

if len(sys.argv) < 3:
    print 'usage: %s img1 img2' % sys.argv[0]
    sys.exit(1)

img1_path = sys.argv[1]
img2_path = sys.argv[2]

img1 = cv2.imread(img1_path, cv2.CV_LOAD_IMAGE_GRAYSCALE)
img2 = cv2.imread(img2_path, cv2.CV_LOAD_IMAGE_GRAYSCALE)

detector = cv2.FeatureDetector_create("SURF")
descriptor = cv2.DescriptorExtractor_create("BRIEF")
matcher = cv2.DescriptorMatcher_create("BruteForce-Hamming")

# detect keypoints
kp1 = detector.detect(img1)
kp2 = detector.detect(img2)

print '#keypoints in image1: %d, image2: %d' % (len(kp1), len(kp2))

# descriptors
k1, d1 = descriptor.compute(img1, kp1)
k2, d2 = descriptor.compute(img2, kp2)

print '#keypoints in image1: %d, image2: %d' % (len(d1), len(d2))

# match the keypoints
matches = matcher.match(d1, d2)

# visualize the matches
print '#matches:', len(matches)
dist = [m.distance for m in matches]

print 'distance: min: %.3f' % min(dist)
print 'distance: mean: %.3f' % (sum(dist) / len(dist))
print 'distance: max: %.3f' % max(dist)

# threshold: half the mean
thres_dist = (sum(dist) / len(dist)) * 0.5

# keep only the reasonable matches
sel_matches = [m for m in matches if m.distance < thres_dist]

print '#selected matches:', len(sel_matches)

# #####################################
# visualization
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
view = sp.zeros((max(h1, h2), w1 + w2, 3), sp.uint8)
view[:h1, :w1, 0] = img1
view[:h2, w1:, 0] = img2
view[:, :, 1] = view[:, :, 0]
view[:, :, 2] = view[:, :, 0]

for m in sel_matches:
    # draw the keypoints
    # print m.queryIdx, m.trainIdx, m.distance
    color = tuple([sp.random.randint(0, 255) for _ in xrange(3)])
    cv2.line(view, (int(k1[m.queryIdx].pt[0]),int(k1[m.queryIdx].pt[1])), (int(k2[m.trainIdx].pt[0] + w1), int(k2[m.trainIdx].pt[1])), color)

cv2.imshow("view", view)
cv2.waitKey()



実行結果

結果は以下のようになります。

result.png


無事結果が表示されました ε-(´∀`*)ホッ

C#からIronPythonを呼び出すために、調べていた際にはまったことをメモ。

簡単なスクリプトやメソッドなら呼び出せるのですがimport numpyやimport waveなどを使用すると
下記のようなエラーが・・・






メッセージ内容を見ると

IronPython.Runtime.Exceptions.ImportException はハンドルされませんでした。
Message=No module named numpy


とのこと、

DLLのロードができていないようなのですが、
他のサイトでは連携の際に上記現象の記載がない方もいらっしゃるようでこのへんは謎です。



ソース

エラーの原因は、IronPythonでロードができていないようです。
強調された箇所を追加することによって実行ができるようになりました。
#もっといい手法あるような気がしますが、調べても出てこないので。。。

ソースは以下のようになります。

Python
#-*- coding: utf-8 -*-
import sys
sys.path.append(r'C:\Program Files\IronPython 2.7')
sys.path.append(r'C:\Program Files\IronPython 2.7\DLLs')
sys.path.append(r'C:\Program Files\IronPython 2.7\Lib')
sys.path.append(r'C:\Program Files\IronPython 2.7\Lib\site-packages')

import clr
clr.AddReference('mtrand.dll')

import numpy as np

result = np.sin(input)



C#
次にC#です。
以下の2つのDLLを参照の追加を行い。
  • IronPython.dll
  • Microsoft.Scripting.dll


その後、usingの追加を行ってください。
  • using IronPython.Hosting;
  • using Microsoft.Scripting.Hosting;
// Pythonスクリプト実行エンジン
ScriptEngine engine = Python.CreateEngine();

// 実行するPythonのソースを指定
ScriptSource source = engine.CreateScriptSourceFromFile("../../sample.py");

// 実行エンジンに渡す値を設定する
ScriptScope scope = engine.CreateScope();

// Pythonに渡す値を設定(inputという変数に40を設定)
scope.SetVariable("input", 40);

// 実行
source.Execute(scope);

// Pythonの実行結果を取得
double result = scope.GetVariable("result");




IronPythonでの計算、C#側で計算結果の受け取りができることを確認しました。
もっと良い方法があるのかもしれませんが、この辺であきらめましたorz


若干ロードがあるせいか遅い気がしますが、IronPythonのnumpyなどのライブラリがC#で使えるのは大きなメリットかなと思います。

一生懸命POCを実装していましたが、
OpenCV内にphaseCorrelateとしてPOCが定義されているのを発見しました。

ヘルプなどあさってみましたが特に記載されていないため、
まだベータ版なのかもしれませんが問題なく動作していたためご紹介を

opencvフォルダ内の以下のディレクトリにそれぞれ格納されていました。
関数自体の定義
modules\imgproc\src\phasecorr.cpp
モジュール(?)のテスト
modules\imgproc\test\test_pc.cpp
使用方法
samples\cpp\phase_corr.cpp



ソース

phase_corr.cppをそのまま転載します。

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;

int main(int, char* [])
{
    VideoCapture video(0);
    Mat frame, curr, prev, curr64f, prev64f, hann;
    int key = 0;

    do
    {
        video >> frame;
        cvtColor(frame, curr, CV_RGB2GRAY);

        if(prev.empty())
        {
            prev = curr.clone();
            createHanningWindow(hann, curr.size(), CV_64F);
        }

        prev.convertTo(prev64f, CV_64F);
        curr.convertTo(curr64f, CV_64F);

        Point2d shift = phaseCorrelate(prev64f, curr64f, hann);
        double radius = cv::sqrt(shift.x*shift.x + shift.y*shift.y);

        if(radius > 5)
        {
            // draw a circle and line indicating the shift direction...
            Point center(curr.cols >> 1, curr.rows >> 1);
            cv::circle(frame, center, (int)radius, cv::Scalar(0, 255, 0), 3, CV_AA);
            cv::line(frame, center, Point(center.x + (int)shift.x, center.y + (int)shift.y), cv::Scalar(0, 255, 0), 3, CV_AA);
        }

        imshow("phase shift", frame);
        key = waitKey(2);

        prev = curr.clone();
    } while((char)key != 27); // Esc to exit...

    return 0;
}



27行目がPOCです。画像を渡すとPoint2dで座標が返却されます。
動作内容はカメラから画像(フレーム)を取得し、前のフレームと比較しカメラがどちらに動いているか判定するようです。
移動方向をフレーム中心の円の大きさを用いて表示するようになっております。

参考までにご紹介です。
OpenCVSharpの公式サイトに記載されているので、ご存じかもしれませんが。
< デバッグ中にIplImageの中を確認する方法をメモしておきます。

DebuggerVisualizer - opencvsharp http://code.google.com/p/opencvsharp/wiki/DebuggerVisualizer

導入方法

OpenCVSharpの中に含まれているdllの中に

OpenCvSharp.DebuggerVisualizers.dll

があります。
それを、My DocumentのVisual StudioのVisualizersというフォルダにコピーします。

VistaでVisual Studio2010の例ですと。
C:\Users\XXX\Documents\Visual Studio 2010\Visualizers
になります。


使い方

デバッグ中にIplImageの変数にフォーカスを当てると、虫メガネのマークが表示されるので
それをクリックすると現在の状況の画像が表示されます。

FC2カウンター
プロフィール

詠み人知らず

Author:詠み人知らず
プログラム好きな名もなき凡人がお送りしています。(得意とは言っていない
最近の興味はPython、C#、Matlab(Octave)、画像処理、AR(拡張現実)、統計などなど・・・

気分で思いついたことを書くため話題に一貫性がないかもしれません。

カレンダー
09 | 2017/10 | 11
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -
最新記事
タグクラウドとサーチ

カテゴリ
最新コメント
最新トラックバック
月別アーカイブ