作成者別アーカイブ: はごろも いかお

はごろも いかお について

・画像のピクセルフォーマットや画素のバイナリデータ加工 ・組み込み系Linux ・router なんかの開発をC/C++でやっているジジイです 「六本木は萌えているか」 萌えます萌えます

tesseract-ocrをためしましたが何か?

タグ: | 投稿日: 投稿者:

tesseract-ocrという画像から文字を認識する処理を試しました
かなりお手軽に実験できます

・ソースコードを取ってくる
# wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.02.tar.gz
・日本語の翻訳ファイルと英語のファイル(これがないと怒られる)
# wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.jpn.tar.gz
# wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.eng.tar.gz

・解凍
tar -zxvf tesseract-ocr-3.02.02.tar.gz
tar -zxvf tesseract-ocr-3.02.jpn.tar.gz
tar -zxvf tesseract-ocr-3.02.eng.tar.gz

・ビルド(INSTALLを読んでの手順)
#./autogen.sh
・おっと、私の環境では(ubuntu 13.10)
libtool とかleptonicaが無いと怒られましたので

# apt-get install libtool libleptonica-dev
・再度ビルド
# ./autogen
# ./configure
# make
# make check
・上手くいったっぽいので
# make install
・で早速sampleを(eurotext.tif)をキャプチャしようとすると
# tesseract ./eurotext.tif testDoc
Error opening data file /usr/local/share/tessdata/eng.traineddata
Please make sure the TESSDATA_PREFIX environment variable is set to the parent directory of your “tessdata” directory.
Failed loading language ‘eng’
Tesseract couldn’t load any languages!
Could not initialize tesseract.

・で、/usr/local/share/tessdata/ に英語と日本語の翻訳ファイルを置きます
# sudo cp -i tesseract-ocr/tessdata/jpn.traineddata /usr/local/share/tessdata/.
# sudo cp -i tesseract-ocr/tessdata/eng.traineddata /usr/local/share/tessdata/.

・実行してみました
# tesseract ./eurotext.tif testDoc

こいつが
eurotext
こんな風に
testDoc

ただブラウザでみると壊れてるっぽくみえますが、これヨーロッパ系文字なのね
結構変換してます。

で。今度は日本語じゃん!
こんなのを
mokkai

# tesseract mokkai.tiff testText -l jpn

こうなった
testText
ダメダメじゃん

と思ったら学習ってあるのね。今度しっかり勉強させた奴を紹介しますね。

* 画像は本当はtifを使ったのですが、なんか表示されないのでjpegに変換してます
** tesseract-ocrはgoogle先生が開発してるんですって


OpenCvの顔認識で遊びました

タグ: | 投稿日: 投稿者:

OpenCVで顔認識を行って適当なところに目線も入れてみました。
モデルは弊社映像スタッフでございます。

結果として誤認識も結構ありますが、お手軽に作った割にはなかなかです。

これが動画

こちらが静止画

blogSample

ソースコード的にはこんな感じです。モルフォロジーしたりエッジを求めたら
精度が上がるかな?と思ったけれど見当違いでした。

#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <stdio.h>

main(int argc, char* argv[]) {
        char    haacFile[1024];
        memset(haacFile, 0x00, sizeof(haacFile));
        strcpy(haacFile, "haarcascade_frontalface_alt.xml");
        if(argc < 3){                 printf("Enter input video, and Output video file name.\n");                 return 2;         } else if(argc > 3){
                memset(haacFile, 0x00, sizeof(haacFile));
                strcpy(haacFile, argv[3]);
        }
        CvHaarClassifierCascade *cvHCC = (CvHaarClassifierCascade*)cvLoad(haacFile);
        if(cvHCC == NULL) return 1;
        CvMemStorage* cvMStr = cvCreateMemStorage(0);
//      cvNamedWindow("Example2_10", CV_WINDOW_AUTOSIZE);
        cvNamedWindow("FaceDetect", CV_WINDOW_AUTOSIZE);
        CvCapture *capture = cvCreateFileCapture(argv[1]);
        if(!capture){
                return -1;
        }
        IplImage *bgr_frame;
        double fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
        printf("fps=%d\n", (int)fps);

        CvSize size = cvSize((int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH),
                        (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT));

        printf("frame (w, h) = (%d, %d)\n", size.width, size.height);

        CvVideoWriter *writer = cvCreateVideoWriter(argv[2], CV_FOURCC('D', 'X', '5', '0'), fps, size);

//      IplImage *canny_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
//      IplImage *temp = cvCreateImage(size, IPL_DEPTH_8U, 1);

        IplImage *gray_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
        while((bgr_frame = cvQueryFrame(capture)) != NULL){
                cvCvtColor(bgr_frame, gray_frame, CV_BGR2GRAY);
//              cvMorphologyEx(gray_frame, canny_frame, temp, NULL, CV_MOP_CLOSE, 1);
//              cvCanny(gray_frame, canny_frame, 60, 128, 3);
                CvSeq *face = cvHaarDetectObjects(gray_frame, cvHCC, cvMStr);
//              cvShowImage("Example2_10", bgr_frame);
                for (int i=0;i < face->total;i++){
                        CvRect *faceRect = (CvRect*)cvGetSeqElem(face, i);
                        cvRectangle(bgr_frame,
                                        cvPoint(faceRect->x, faceRect->y + ((faceRect->height / 10) * 2)),
                                        cvPoint(faceRect->x + faceRect->width, faceRect->y + ((faceRect->height / 10) * 6)),
                                        CV_RGB(0, 0 ,0), CV_FILLED, CV_AA);
                }
                cvShowImage("FaceDetect", bgr_frame);

                cvWriteToAVI(writer, bgr_frame);
                char c = cvWaitKey(10);
                if(c == 27) break;
        }
        cvReleaseVideoWriter(&writer);
        cvReleaseImage(&gray_frame);
//      cvReleaseImage(&canny_frame);
        cvReleaseCapture(&capture);
}


プレモルの宣伝でやってるエフェクトを真似してみた(その方式).vol2

タグ: | 投稿日: 投稿者:

いかおです。

前回の「プレモルの宣伝でやってるエフェクトを真似して」の続きです。

一つ一つのピクセルがuyvy422でくるとなると、hueへの変換は以下の様になります

まず、RGBにします。
R = 1.000Y + 1.402V
G = 1.000Y – 0.344U – 0.714V
B = 1.000Y + 1.772U

hue = 180 / π * atan2(√3 * (GB), 2 * R – (float)GB)

※double atan2(double y, double x); // math.h のやつね

これでHueがマイナスである場合がありますので、マイナスだったら
360を足します

これでやうやくHueになります。

こんな計算を例えば(たかだか)1080iでやろうとすると
毎秒この計算を、1920x1080x30 回やりますとかなりゴーヂャスなPCでも間に合いません

確かにこのままやったら再生が間に合わなかった
で、最初に全パターン計算しといてテーブルに格納するんです
マッチングテーブルですねぇ・・・

ただ、yuv値ってそれぞれ(この場合)8bitですが、実際の値の範囲は

y 16~235
u(cb)/ v(cr) 16~240

こんな感じになりますが、とりあえず全部作っちゃえってんで、ソースコード公開!!
★RGB全パターンからHueを求めてYUVのテーブルに押し込みます。

.
#define KOSUU     256
.
.
    memset((char *)YUVTable, 0x00, sizeof(uint16_t) * KOSUU * KOSUU * KOSUU);
    double root3 = sqrt(3);
    float  hue;
    for(int ir=0;ir < KOSUU;ir++){
        for(int ig=0;ig < KOSUU;ig++){
            for(int ib=0;ib < KOSUU;ib++){
                float y, u, v;
                uint8_t ucy, ucu, ucv;
                y = (0.299f  * ir) + (0.577f * ig) + (0.114f * ib);
                u = (-0.169f * ir) - (0.331f * ig) + (0.5f   * ib);
                v = (0.5f    * ir) - (0.419f * ig) - (0.081f * ib);
                if((round(y) < 0.0f) || (round(y) > 255.0f)){
                    syslog(LOG_ERR, "Y overfloow at(%d:%d:%d)", ir, ig, ib);
                    continue;
                }
                if((ir == 0) && (ig == 0) && (ib == 255)){
                    u = 255.0f;
                } else if((round(u + 128.0f) < 0.0f) || (round(u + 128.0f) > 255.0f)){
                    syslog(LOG_ERR, "U overfloow at(%d:%d:%d)", ir, ig, ib);
                    continue;
                }
                if((ir == 255) && (ig == 0) && (ib == 0)){
                    v = 255.0f;
                } else if((round(v + 128.0f) < 0.0f) || (round(v + 128.0f) > 255.0f)){
                    syslog(LOG_ERR, "V overfloow at(%d:%d:%d)", ir, ig, ib);
                    continue;
                }
                ucy = (uint8_t)round(y);
                ucu = (uint8_t)round(u + 128.0f);
                ucv = (uint8_t)round(v + 128.0f);
                hue = 180 / M_PI * atan2(root3 * ((float)ig - (float)ib), 2 * (float)ir - (float)ig - (float)ib);
                if(hue < 0.0f) hue = hue + 360;
                YUVTable[(ucy * KOSUU * KOSUU) + (ucu * KOSUU) + ucv] = (uint16_t)round(hue);
             }
         }
     }

これを、Hue中央値とレンジを指定させといて、比較のため”0″変位に置き換えて

 // m_hue   ..中央値
 // m_range ..レンジ
 // m_gap   ..変位値(0変位比較のための加算する値) 
 // こんな風にしといて         
 if((m_hue + m_range) > 360)
    m_high = (m_hue + m_range) - 360;
  else
    m_high = m_hue + m_range;

  if(((int)m_hue - (int)m_range) < 0)
      m_low = ((int)m_hue - (int)m_range) + 360;
  else
      m_low = m_hue - m_range;         if(m_low > m_high){

  m_gap = 360 - m_low;
  m_low = 0;
  m_high = m_high + m_gap;
......
  uint16_t nowHue = YUVTable[(y * KOSU * KOSU) + (u * KOSU) + v] + m_gap;
  if(nowHue > 360) nowHue = nowHue - 360;
  if((nowHue <= m_low) || (nowHue >= m_high)){
      // モノ黒にする
  }

で、前回のサンプルでもいまいちキレイじゃないので、調査の上、
キレイにして掲載します(いずれね)


プレモルの宣伝でやってるエフェクトを真似してみた(その方式)

タグ: | 投稿日: 投稿者:

いかおです

映像関係のネタです

サントリープレミアムモルツのコマーシャルでやっているビールだけが黄金色に輝くエフェクトなんですが、やってみたいと思いました。

実はNFLの中継でピンクリボン期間に放映されたCF(?)で選手が身につけたピンク色のモノだけ発色しているのを見て実際にやってみようと考えたわけです。

先ず、ソースとしてUYVY422が入ってきて特定の色以外はモノにするので各画素のUとVは両方共”128″に塗り替えます(U,Y,Vそれぞれ8bit。1画素あたりは16bitね)。そういった画素データの書き換えで簡単にモノクロにはできるわけですね。そして、特定の色としてヒットした場合はそのまま加工せずにおいておけば、目的の効果が出きるはずですね。これなら数フレームの遅延でライブにも利用できます。

さて、特定の色の指定なのですが、前提がRGBではなくUYVY(CrYCbY)なので隣り合う2つの画素は2画素で1つの色です(キリ!)。ここで、uyvyからrgbを求めたところで色として判定に困るのでさらに変換して色相(Hue)を基準にして判定することにします。今回はここでおしまい。次回はそのHueの求め方から

※ちょっと赤色でやってみた

★元はこんな感じ