アプリ版:「スタンプのみでお礼する」機能のリリースについて

現在opencvで画像処理をしながら、別スレッドでmbedから送られてくる文字を表示するプログラムを作っています。
しかし、一度目は正しく動作するのですがプログラムを終了して2度目を開始するとシリアルポートを開くところで停止してしまいます。mbedを取り外すと正しくエラーが表示されており、もう一度mbedを接続しプログラムを実行すると正常に接続がされますが、2度目を開始すると、やはりシリアルポートを開くところで停止してしまいます。
環境はlinuxでc++です。プログラムは以下のようにしています。
#include <opencv2/objdetect/objdetect.hpp>
//////省略/////
using namespace cv;
using namespace std;
/////////camera設定//////////
#define CAM_W 320
#define CAM_H 240
#define WINNAME "camera"
#define pixel_8UC1(img,x,y) *((img)->data + ((img)->cols * (y) + (x)))
#define pixel_8UC3(img,x,y,c) *((img)->data + ((img)->cols * 3 * (y) + 3 * (x) + (c)))
#define RGB_DIFF 50
#define BUFFSIZE 256
/////////camera設定//////////
#define BAUDRATE B9600
#define MODEMDEVICE "/dev/tty.usbmodem1422"
#define BUFFSIZE 256
#define COULDNOTFORK -1
#define FALSE 0
#define TRUE 1
volatile int STOP = FALSE;
static int fd = -1;

void serial_init(int fd) {
struct termios tio;
memset(&tio, 0, sizeof(tio));
tio.c_cflag = CS8 |CLOCAL| CREAD;
tio.c_iflag = 0;
tio.c_oflag = 0;
tio.c_lflag = 0;
tio.c_cc[VMIN]= 1;
tio.c_cc[VTIME] = 0;
tio.c_lflag = ICANON;
tio.c_iflag = IGNPAR | ICRNL;
// ボーレートの設定
cfsetispeed(&tio, BAUDRATE);
cfsetospeed(&tio, BAUDRATE);
// デバイスに設定を行う
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &tio);
}
void *thred_func(void* std){
struct termios oldtio, newtio;
char buf[BUFFSIZE];
int count;
int check;
fd = open(MODEMDEVICE,O_RDWR|O_NOCTTY);//2度目以降ここで止まってしまいます
printf("serial OK \n");
if (fd < 0) {
perror(MODEMDEVICE);
return NULL;
}
tcgetattr(fd,&oldtio); /* 現在のシリアルポートの設定を待避させる*/
bzero(&newtio, sizeof(newtio));
serial_init(fd);
printf("recive\n");
while (FALSE == STOP) {
memset(&buf, 0, sizeof(buf));
count = read(fd, &buf, BUFFSIZE);
if (count < 0) {
fprintf(stdout, "CHILD:Could not read from serial port\n");
STOP = TRUE;
} else {
fprintf(stdout, "CHILD:RCVD CHAR %s %d \n", buf, count);
}
}
tcsetattr(fd,TCSANOW,&oldtio);
check = close(fd);
if (check != 0) {
printf("error\n");
}
fprintf(stdout, "CHILD:BYE!\n");
return NULL;
}
void construct_2(Mat src,Mat back_img,Mat *dst,Mat *mask){
............
}

int main(){
Mat frame,disp_img;
Mat background_img,mask,sub_img;
VideoCapture cap;
int key,state;
int flag = 0;
pthread_t th;
int stat;
char buf[BUFFSIZE];
stat = pthread_create(&th, NULL, thred_func, (void*)(buf));
cap.open(0);
if (!cap.isOpened())
return (1);
cap.set(CV_CAP_PROP_FRAME_WIDTH, CAM_W);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, CAM_H);
disp_img.create(Size(CAM_W, CAM_H),CV_8UC3);
background_img.create(Size(CAM_W, CAM_H),CV_8UC3);
mask.create(Size(CAM_W, CAM_H),CV_8UC1);
cap.read(frame);
background_img = frame.clone();
printf("start");
while (1) {
if (cap.grab() == false) {
printf("grab error\n");
continue;
}
if (cap.retrieve(frame,0) == 0) {
printf("retrieve error\n");
continue;
}
construct_2(frame, background_img, &disp_img, &mask);
imshow(WINNAME, disp_img);//結果の表示
blur(mask, mask, Size(5,5));
imshow("mask", mask);
////////何かキーが押されたら画像処理終了/////////
key = waitKey(1);
if(key >= 0){
switch (key) {
case 0x73:
background_img = frame.clone();
break;
default:
fprintf(stderr,"\nkey input %x\n",key);
flag = 1;
break;
}
}
if (flag != 0) {
break;
}
}
STOP = TRUE;
cap.release();
disp_img.release();
destroyWindow(WINNAME);
return(0);
}

A 回答 (2件)

> プログラムを終了して2度目を開始するとシリアルポートを開くところで停止してしまいます。


このプログラムを終了ってメインスレッドを終了するのですよね。このときシリアル通信しているスレッドの方は正しく終了処理していないですよね。
シリアル通信が正しくクローズされていないので再オープンの際に待ちに入ってしまっているのではないかと思います。mbedを外すとシリアル回線がリセットされて次のオープンでは上手くいくのでしょう。
プログラム終了時に通信スレッドを止めてシリアル回線をクローズする必要があるでしょう。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。マルチスレッドを使わずにシリアルポートをオープンするだけのプログラムでも同じ問題があったのですが、シリアルポートを”dev/tty.usbmodem1422”から”dev/cu.usbmodem1422”へ変更することで解決しました。

お礼日時:2016/05/27 19:10

> プログラムを終了して2度目を開始するとシリアルポートを開くところで停止してしまいます。


このプログラムを終了ってメインスレッドを終了するのですよね。このときシリアル通信しているスレッドの方は正しく終了処理していないですよね。
シリアル通信が正しくクローズされていないので再オープンの際に待ちに入ってしまっているのではないかと思います。mbedを外すとシリアル回線がリセットされて次のオープンでは上手くいくのでしょう。
プログラム終了時に通信スレッドを停止してシリアル回線をクローズする処理を入れる必要があると思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。シリアルポートを”dev/tty.usbmodem1422”から”dev/cu.usbmodem1422”へ変更することで解決しました。

お礼日時:2016/05/27 19:10

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!