OpenCVで処理するための画像の変換について

877 views
Skip to first unread message

Kyaiktiyo

unread,
Dec 15, 2016, 1:46:32 AM12/15/16
to ROS JAPAN Users Group
USBカメラから取得した映像をOpenCVを用いて処理したいと考えているのですが、ROSの形式の状態の映像をどのようにOpenCVの形式に変換すればいいのでしょうか?
お力をお貸しください。

以下は現在作成段階のプログラムです。
メイン関数にある image_subはROSのUSBカメラノードから取得した画像を表しています。
これをOpenCVの形式に変換してそれ以降の while True: の部分の処理を行いたいと考えています。
現在、 while True: 以降のOpenCVの処理の部分で画像を代入する部分にはROS形式である image_subを代入しているため、当然エラーが発生します。
このimage_subをOpenCV形式に変換したいというのが現段階の課題です。
どうか、ご回答よろしくお願いします。
何かご不明な点がございましたらご質問ください。

import sys, time
import rospy
import cv2
import numpy as np
from sensor_msgs.msg import Image
from std_msgs.msg import UInt16

class ParticleFilter:
    def __init__(self):
        self.SAMPLEMAX = 1000
        self.height, self.width = 480, 640

    def initialize(self):
        self.Y = np.random.random(self.SAMPLEMAX) * self.height
        self.X = np.random.random(self.SAMPLEMAX) * self.width

    def modeling(self):
        self.Y += np.random.random(self.SAMPLEMAX) * 20 - 10
        self.X += np.random.random(self.SAMPLEMAX) * 20 - 10

    def normalize(self, weight):
        return weight / np.sum(weight)

    def resampling(self, weight):
        index = np.arange(self.SAMPLEMAX)
        sample = []

        for i in range(self.SAMPLEMAX):
            idx = np.random.choice(index, p=weight)
            sample.append(idx)

        return sample

    def calcLikelihood(self, image):
        mean, std = 250.0, 10.0
        intensity = []

        for i in range(self.SAMPLEMAX):
            y, x = self.Y[i], self.X[i]
            if y >= 0 and y < self.height and x >= 0 and x < self.width:
                intensity.append(image[y,x])
            else:
                intensity.append(-1)

        weights = 1.0 / np.sqrt(2 * np.pi * std) * np.exp(-(np.array(intensity) - mean)**2 /(2 * std**2))
        weights[intensity == -1] = 0
        weights = self.normalize(weights)
        return weights

    def filtering(self, image):
        self.modeling()
        weights = self.calcLikelihood(image)
        index = self.resampling(weights)
        self.Y = self.Y[index]
        self.X = self.X[index]


        return np.sum(self.Y) / float(len(self.Y)), np.sum(self.X) / float(len(self.X))


if __name__=='__main__':
    rospy.init_node('tracking')

    image_sub = rospy.Subscriber('/usb_cam/image_raw', Image)

    filter = ParticleFilter()
    filter.initialize()

    while True:
        gray = cv2.cvtColor(image_sub, cv2.COLOR_RGB2GRAY)
        y, x = filter.filtering(gray)
        cv2.circle(image_sub, (int(x), int(y)), 10, (0, 0, 255), -1)
        for i in range(filter.SAMPLEMAX):
            cv2.circle(image_sub, (int(filter.X[i]), int(filter.Y[i])), 2, (0, 0, 255), -1)
        cv2.imshow('pf', image_sub)
        if cv2.waitKey(20) & 0xFF == 27:
            break

    try:
        rospy.spin()
    except KeyboardInterrupt:
        pass

Junya Hayashi

unread,
Dec 15, 2016, 9:39:32 AM12/15/16
to ROS JAPAN Users Group
Kyaiktiyo さん

ROS の Image 型と OpenCV の Mat 型の間の変換処理には cv_bridge パッケージが役に立ちます。
こちらのチュートリアルをご覧ください。

なお、 rospy.Subscriber の返り値は Subscriber オブジェクト(購読をやめて unregister するときに利用する)
であって、 Image ではありません。 トピックから Image 型のメッセージを受け取るには、 rospy.Subscriber の
第3引数に callback 関数を指定する必要があります。

ご参考まで。

林 淳哉


2016年12月15日 15:46 Kyaiktiyo <musashi....@gmail.com>:

--
このメールは Google グループのグループ「ROS JAPAN Users Group」に登録しているユーザーに送られています。
このグループから退会し、グループからのメールの配信を停止するには ros-japan-users+unsubscribe@googlegroups.com にメールを送信してください。
その他のオプションについては https://groups.google.com/d/optout にアクセスしてください。

Kyaiktiyo

unread,
Dec 15, 2016, 9:00:31 PM12/15/16
to ROS JAPAN Users Group
林淳哉 様
ご回答ありがとうございます。
記載していただいたサイトを含め調べながら見様見真似で以下のようにプログラムを改善してみました。
しかし、このようなエラーがでてしまいます。

Traceback (most recent call last):
  File "pf.py", line 83, in <module>
    gray = cv2.cvtColor(cv_image, cv2.COLOR_RGB2GRAY)
NameError: name 'cv_image' is not defined

原因はcv_imageを渡していることだという事はわかるのですが。
どのように改善するべきなのでしょうか?


import sys, time
import rospy
import cv2
import numpy as np
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
from std_msgs.msg import UInt16


def callback(self, data):
    try:
        cv_image = self.bridge.imgmsg_to_cv2(data, 'bgr8')
    except CvBridgeError, e:
        print e

    cv_image = np.array(cv_image, dtype=np.uint8)
    image_sub = rospy.Subscriber('/usb_cam/image_raw', Image, callback)
    bridge = CvBridge()


    filter = ParticleFilter()
    filter.initialize()

    while True:
        gray = cv2.cvtColor(cv_image, cv2.COLOR_RGB2GRAY)
        y, x = filter.filtering(gray)
        cv2.circle(cv_image, (int(x), int(y)), 10, (0, 0, 255), -1)
        for i in range(filter.SAMPLEMAX):
            cv2.circle(cv_image, (int(filter.X[i]), int(filter.Y[i])), 2, (0, 0, 255), -1)
        cv2.imshow('pf', cv_image)

        if cv2.waitKey(20) & 0xFF == 27:
            break
    try:
        rospy.spin()
    except KeyboardInterrupt:
        pass




2016年12月15日木曜日 23時39分32秒 UTC+9 Junya Hayashi:
このグループから退会し、グループからのメールの配信を停止するには ros-japan-use...@googlegroups.com にメールを送信してください。
その他のオプションについては https://groups.google.com/d/optout にアクセスしてください。

Reply all
Reply to author
Forward
0 new messages