アーカイブ

‘C言語’ タグのついている投稿

画像のだいたいの色を求める

2009 年 12 月 24 日 shokai コメント 2 件
カテゴリー: 未分類 タグ: , ,

カメラの入力画像から平均的な色を求めてRGBで出力する。
頻出色じゃなくて、全体的に赤っぽかったらr:200,g:50,b:50みたいなかんじで出す。赤っぽいとか青っぽいとかを求めたい。


数えて平均出そうかと思ったけどOpenCVで1×1ピクセルの画像にリサイズしてしまうのが速い&早いことに気づいた。
一応カメラのプレビューと、その色で塗りつぶしたウィンドウを出してみている。1ピクセルの画像はcvShowImageできないので、表示のために2ピクセルの画像を作っている
image1px.cpp

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

int main(int argc, char** argv) {
  CvCapture *capture;
  IplImage *img, *img1px, *imgR, *imgG, *imgB, *img2px;
  img1px = cvCreateImage(cvSize(1,1), IPL_DEPTH_8U, 3);
  imgR = cvCreateImage(cvSize(1,1), IPL_DEPTH_8U, 1);
  imgG = cvCreateImage(cvSize(1,1), IPL_DEPTH_8U, 1);
  imgB = cvCreateImage(cvSize(1,1), IPL_DEPTH_8U, 1);
  img2px = cvCreateImage(cvSize(2,2), IPL_DEPTH_8U, 3);
  
  char *winNameCapture = "Capture";
  char *winName1px = "Image1px";
  cvNamedWindow(winNameCapture, CV_WINDOW_AUTOSIZE);
  cvNamedWindow(winName1px, CV_WINDOW_AUTOSIZE);
  capture = cvCreateCameraCapture(0);

  while (1) {
    img = cvQueryFrame(capture);
    cvShowImage(winNameCapture, img);
    cvResize(img, img1px, CV_INTER_CUBIC);
    cvSplit(img1px, imgB, imgG, imgR, NULL);
    printf("r:%d, g:%d, b:%d\n", 
           (unsigned char)imgR->imageDataOrigin[0],
           (unsigned char)imgG->imageDataOrigin[0],
           (unsigned char)imgB->imageDataOrigin[0]);
    cvResize(img1px, img2px, CV_INTER_CUBIC);
    cvShowImage(winName1px, img2px);
    if (cvWaitKey(33) == 'q') break;
  }
  
  cvReleaseCapture(&capture);
  cvDestroyWindow(winNameCapture);
  cvDestroyWindow(winName1px);
  return 0;
}


Makefile
SRC = image1px.cpp
DST = image1px

prefix=/opt/local
CV_INCPATH=$(prefix)/include/opencv
CV_LIBPATH=$(prefix)/lib 

CV_LIBS= -lcv -lcvaux -lcxcore -lhighgui 

all:
g++ -O $(SRC) -o $(DST) -I$(CV_INCPATH) -L. -L$(CV_LIBPATH) $(CV_LIBS)


赤いポストイットをカメラの前に
平均的な色を取得
出力
赤いことがわかる
r:186, g:61, b:61
r:186, g:61, b:61
r:191, g:63, b:61
r:198, g:67, b:63
r:200, g:69, b:63


平均的な色を取得
白い。
r:149, g:146, b:147
r:159, g:155, b:156
r:169, g:156, b:159
r:169, g:160, b:161
r:169, g:159, b:161
r:169, g:159, b:161


平均的な色を取得
赤黒いのかな?
r:126, g:92, b:124
r:126, g:92, b:124
r:126, g:92, b:124
r:126, g:92, b:124
r:126, g:92, b:124
r:126, g:92, b:124
r:125, g:92, b:124


平均的な色を取得
白い
r:126, g:119, b:126
r:126, g:119, b:126
r:126, g:119, b:125
r:125, g:118, b:125
r:125, g:118, b:125
r:125, g:118, b:125
r:125, g:118, b:125

Cでgearman workerを書いてRubyのclientから呼び出す

2009 年 12 月 15 日 shokai コメントはありません
カテゴリー: 未分類 タグ: , , , ,

gearmandをソースからインストールして、Cライブラリのlibgearmanが使えるようになった。

これでC言語でworkerを作ってRubyのclientから呼び出せる。環境はUbuntu9.04とgearmand0.11


■Cでworkerを書く
str_reverseというアビリティを持つworkerを作る。
ほぼAPIドキュメントのままだが、jobの引数を受け取るのと、値を返せるようにがんばった。ジョブ失敗した時とかのエラー処理全然書いてない。たぶんenum gearman_return_tを返せばいいんだろうけど

strreverse-worker.c

// 文字列をreverseして返すworker
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgearman/gearman.h>

void *job_str_reverse(gearman_job_st *job, void *cb_arg, size_t *result_size,
       gearman_return_t *ret_ptr)
{
  char *str = (char *)gearman_job_workload(job);
  int len = strlen(str);
  printf("str:%s  length:%d\n", str, len);

  char reverse[len];
  for(int i = 0; i < len; i++){
    reverse[i] = str[len-i-1]; // 文字列を逆にする
  }

  char *result = strdup(reverse); // 結果の文字列はコピーしてポインタで返す
  *result_size= gearman_job_workload_size(job);
  *ret_ptr= GEARMAN_SUCCESS;
  return result;
}


int main(int argc, char *argv[])
{
  gearman_return_t ret;
  gearman_worker_st worker;

  gearman_worker_create(&worker);
  gearman_worker_add_server(&worker, "127.0.0.1", 7003);
  gearman_worker_add_function(&worker, "str_reverse", 0, job_str_reverse, NULL);
  
  while(1) gearman_worker_work(&worker); // ジョブ登録したらループで待つ

  gearman_worker_free(&worker);
  return 0;
}


Makefile
# Linux用Makefile
SRC = strreverse-worker.c
DST = strreverse-worker

prefix=/usr/local
INCPATH=$(prefix)/include
LIBPATH=$(prefix)/lib

GEAR_LIBS=$(LIBPATH)/libgearman.a

all:
g++ -O $(SRC) -o $(DST) -I$(INCPATH)/libgearman -L. -L$(LIBPATH) $(GEAR_LIBS)
makeするとstrreverse-workerができる。


■Rubyでclientを書く
xing-gearman-serverを使うといい

client書く。実行時引数を一つずつstr_reverseに登録するclient。
strreverse-client.rb
#!/usr/bin/env ruby
require 'rubygems'
require 'gearman'

c = Gearman::Client.new(['localhost:7003'])
taskset = Gearman::TaskSet.new(c)

ARGV.each{|str|
  puts "add task #{str}"
  task = Gearman::Task.new('str_reverse', str)
  task.on_complete{|result|
    puts "return: #{str} => #{result}" # 文字列が逆になって返ってくる
  }
  taskset.add_task(task)
}
taskset.wait(100) # wait 100(sec)


■動かしてみる
worker動かす
./strreverse-worker

clientから3つ文字列登録
ruby strreverse-client.rb hello konitiwa asdfhujiko

すると文字列返ってくる
add task hello
add task konitiwa
return: hello => olleh
add task asdfhujiko
return: konitiwa => awitinok
return: asdfhujiko => okijuhfdsa

worker側の標準出力はこうなってた
str:hello  length:5
str:konitiwa length:8
str:asdfhujiko length:10


workerを3つバックグラウンドで起動しておく
./strreverse-worker&
./strreverse-worker&
./strreverse-worker&


凄い勢いで処理されてるので非同期になってるのかよくわからない
ruby strreverse-client.rb hello konitiwa asdfhujiko aaiiaaiiaaii hogehogehogehoge mmmasdffajkl23rwdfv ahsdga9sd8uf9p8u nbjkasdoif98pu
add task hello
add task konitiwa
return: hello => olleh
add task asdfhujiko
return: konitiwa => awitinok
add task aaiiaaiiaaii
return: asdfhujiko => okijuhfdsa
add task hogehogehogehoge
return: aaiiaaiiaaii => iiaaiiaaiiaa
add task mmmasdffajkl23rwdfv
return: hogehogehogehoge => egohegohegohegoh
add task ahsdga9sd8uf9p8u
return: mmmasdffajkl23rwdfv => vfdwr32lkjaffdsammm
add task nbjkasdoif98pu
return: ahsdga9sd8uf9p8u => vfdu8p9fu8ds9agd
return: nbjkasdoif98pu => vfdu8up89fiods

PSoC Designer – CY8C29466の16bit Timer

2007 年 4 月 2 日 shokai コメントはありません
カテゴリー: 未分類 タグ: , , , ,

CY3210-MiniEval基盤にCY8C29466マイコンを置いて、16ビットタイマーを4つ置いて動かした。

1秒毎?ぐらいで動かしてみたが、動いたは動いたけどまだ正確な仕組みがわからない。特にクロックの分周まわり。

ちなみに16bitタイマーはデジタルブロックを2つ消費するので、29466では同時に8個まで使える。

今回はPSoC CPU 基板 (ストロベリーリナックス社) – 趣味の電子工作研究工房 – 楽天ブログ(Blog)がとても参考になった。

■今回のコード

Source Code (PSoC Designer4.3 + C Compiler)

■タイマーの配置とクロック設定

Device EditorのUser Module Selection Viewから選択してくる。

PSoC 16bit Timer

続きを読む…

PSoC Designer – CY8C29466で外部入力割り込み(C言語で)

2007 年 4 月 1 日 shokai コメントはありません

前の記事s.h.log: PSoC Designer – CY8C29466でスイッチ入力と同じ動作を、割り込みでやってみた。

基盤も同じくCY3210-MiniEvalを使った。

動き方もまったく同じのを作っちゃったのでビデオは省略。ただスイッチの扱い方が違うだけ。

SourceCode (PSoC Designer 4.3 + C Compiler)

■動作設定

Device EditorのInterconnect Viewで

PSoC GPIO Interrupt

基本的にs.h.log: PSoC Designer – CY8C29466でスイッチ入力と同じだが、

タクトスイッチの接続されているPORT2-4のInterruptをFailingEdgeにする。

割り込みの仕方は3種類あり、

・FailingEdge → 立下り割り込み

・RisingEdge → 立ち上がり割り込み

・ChangeFromRead → 両エッジ変化割り込み

から選ぶ。

AVRのSIG_INTERRUPT0、SIG_INTERRUPT1はそれぞれINT0, INT1ピンの状態が変化を監視する外部入力割り込みだが、

PSoCの外部入力割込みはAVRのSIG_PIN_CHANGEの方と同じく、どのピンに変化があっても割り込みが発生してしまう。

だから、複数のピンの割り込みを有効にする場合は実際にどのピンの変化が割り込みを発生させたのか?をいちいち確認しなければならない。今回はマスクレジスタで1つのピン(PORT2-4)だけをenableにしているので必要ないけど。

軽くまとめると、PSoCの割り込みの設定は

・マスクレジスタで「どのピンの変化を監視するか」を指定

・ピン毎に「立ち上がり/下がり/両方の、どの条件で割り込むか」を指定

できる。でもこれはPSoC Designerが自動生成してくれるので下手に触る必要は無い。

マスクで複数enableに指定した場合は、実際にどのピンが反応したか?はプログラミングでなんとかする。(1回前のPRTnDRの状態をglobal変数に保存しておいて比較するとか)

この辺ははじめてのPSoCマイコンの「入出力&割り込みのしくみとスイッチ&LEDを使った実験」p.67に詳しく書かれている。

はじめてのPSoCマイコン―周辺アナログ&ディジタル回路を自由自在にプログラミング!! (マイコン活用シリーズ)

続きを読む…

CY8C29466のGPIOでLEDピコピコさせた

2007 年 3 月 17 日 moblog コメントはありません
カテゴリー: 未分類 タグ: , , , ,

「LEDをピコピコさせる」というのは横一列に並べたLEDをマイコンのピンから順番に電流を出したり出さなかったりして順番に点灯させる事を指す。

GPIOの開閉、代入、wait処理、for文if文、インクリメントなどのマイコンプログラミングでよく使う要素が入っているので、新しいマイコンを使う時はこれをやってみる事にしている。

ちなみにGPIOへの入力は、チャタリングやプルアップなど色々あるので別にやる。

LED ピコピコ 検索結果

あと最近知ったけど GPIO はGeneral-Purpose I/Oの略で、つまり汎用ピンの事なんだね。

PSoC MiniProg付属のPSoCMiniEvalにCY8C29466を載せてやってみた。

Source Code(PSoC Designer 4.3 + C Compiler)

動かした。

今回も桑野さんはじめてのPSoCマイコンのp.63-72「入出力&割り込みのしくみとスイッチ&LEDを使った実験」を参考にした。

続きを読む…

track feed