C にしておくと、ソースとオブジェクトの二つのファイルの管理が必要となったり、ライブラリの置く場所など、いろいろめんどう。
というわけで、Python にしてしまおうという計画。
言語文法上で注意するのはこれくらい?
- C の文は「;」で終了するが、Python にはない。
- C の変数宣言では型が必要だが、Python は変数名だけ。
- C では「&」をつけて、その変数のポインタを求めたりするが、Python では不要。
- True/False や Not の表記
- nil や NULL や None の表記
- Python のインデント。
しかし、cv. の後のメソッド名には「cv」がつかない。
ただし、定数名の頭についている「CV」はそのまま残る。
こんな感じ。
C:
frame = cvQueryFrame(capture); cvSmooth(frame, frame, CV_GAUSSIAN, 3, 3);
Python:
frame = cv.QueryFrame(capture) cv.Smooth(frame, frame, cv.CV_GAUSSIAN, 3, 3)
C の cvQueryFrame は Python では cv.QueryFrame となる。
ただし定数は、C で CV_GAUSSIAN、Python で cv.CV_GAUSSIAN となる。
厄介なのがマクロ(?)。Python にはない。ふつーにタプルで表現したりする。
C:
const int w = frame->width; const int h = frame->height; imgR = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); cvCircle(frame, cvPoint(gX, gY), 80, CV_RGB(0,0,255), 6, 8, 0);
Python:
the_size = cv.GetSize(frame) imgR = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1) cv.Circle(frame, (gX, gY), 80, (0, 0, 255), 6, 8, 0)
そのほか、調べないとわからないもの。
C:
cvMoments(imgResult, &moments, 0); double m00 = cvGetSpatialMoment(&moments, 0, 0);
Python:
moments = cv.Moments(cv.GetMat(imgResult, 1), 0) m00 = cv.GetSpatialMoment(moments, 0, 0)
サンプルとして、次のページにあった赤い色のエリアを抽出し、重心を求めるソースの C 版と Python 版を示す。
http://d.hatena.ne.jp/shokai/20090203/1233609981
http://opencv-srf.blogspot.ro/2010/09/object-detection-using-color-seperation.html
これは Mac (10.9.1 Mavericks) と Raspberry Pi で動作確認した。
#include <opencv/cv.h> #include <opencv/highgui.h> // This function threshold the HSV image and create a binary image IplImage* GetThresholdedImage(IplImage* imgHSV) { IplImage* imgResult = cvCreateImage(cvGetSize(imgHSV), IPL_DEPTH_8U, 1); cvInRangeS(imgHSV, cvScalar(150, 160, 60), cvScalar(200, 256, 256), imgResult); return imgResult; } int main() { CvCapture* capture = NULL; IplImage *frame = NULL; IplImage *imgR = NULL, *imgG = NULL, *imgB = NULL; IplImage *imgThreshold_R = NULL, *imgThreshold_G = NULL, *imgThreshold_B = NULL; IplImage *imgTmp = NULL; IplImage *imgHSV = NULL; IplImage *imgResult = NULL; CvMoments moments; capture = cvCaptureFromCAM(0); if (!capture) { printf("Capture failure\n"); return -1; } cvNamedWindow("Video"); cvNamedWindow("Results"); // iterate through each frames of the video while (true) { frame = cvQueryFrame(capture); if (!frame) { break; } frame = cvCloneImage(frame); cvSmooth(frame, frame, CV_GAUSSIAN, 3, 3); // smooth the original image using Gaussian kernel if (1) { const int w = frame->width; const int h = frame->height; imgR = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); imgG = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); imgB = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); imgThreshold_R = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); imgThreshold_G = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); imgThreshold_B = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); imgResult = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); imgTmp = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); cvSplit(frame, imgB, imgG, imgR, NULL); // BGRを分解 // 赤の要素が100以上で、緑と青より1.5倍以上あるピクセルを抽出 cvThreshold(imgR, imgThreshold_R, 100, 255, CV_THRESH_BINARY); cvDiv(imgR, imgG, imgTmp, 10); // 10倍 cvThreshold(imgTmp, imgThreshold_G, 15, 255, CV_THRESH_BINARY); cvDiv(imgR, imgB, imgTmp, 10); cvThreshold(imgTmp, imgThreshold_B, 15, 255, CV_THRESH_BINARY); cvAnd(imgThreshold_G, imgThreshold_B, imgTmp, NULL); cvAnd(imgTmp, imgThreshold_R, imgResult, NULL); cvMoments(imgResult, &moments, 0); double m00 = cvGetSpatialMoment(&moments, 0, 0); double m10 = cvGetSpatialMoment(&moments, 1, 0); double m01 = cvGetSpatialMoment(&moments, 0, 1); int gX = m10 / m00; int gY = m01 / m00; cvCircle(frame, cvPoint(gX, gY), 80, CV_RGB(0,0,255), 6, 8, 0); } else { imgHSV = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3); cvCvtColor(frame, imgHSV, CV_BGR2HSV); // Change the color format from BGR to HSV imgResult = GetThresholdedImage(imgHSV); cvSmooth(imgResult, imgResult, CV_GAUSSIAN, 3, 3); // smooth the binary image using Gaussian kernel } cvShowImage("Results", imgResult); cvShowImage("Video", frame); // Clean up used images cvReleaseImage(&imgHSV); cvReleaseImage(&imgResult); cvReleaseImage(&frame); // Wait 50mS int c = cvWaitKey(10); // If 'ESC' is pressed, break the loop if ((char)c == 0x1b ) { break; } } cvDestroyAllWindows() ; cvReleaseCapture(&capture); return 0; }
Python:
#!/usr/bin/env python # coding: UTF-8 """ DetectingRedObjects.py """ import cv def GetThresholdedImage(imgHSV): imgResult = cv.CreateImage(cv.GetSize(imgHSV), cv.IPL_DEPTH_8U, 1) cv.InRangeS(imgHSV, cv.Scalar(150, 160, 60), cv.Scalar(200, 256, 256), imgResult) return imgResult def main(): capture = None frame = None imgR = imgG = imgB = None imgThreshold_R = imgThreshold_G = imgThreshold_B = None imgTmp = imgHSV = imgResult = None moments = None capture = cv.CaptureFromCAM(0) if (not capture): print("Capture failure") return -1 cv.NamedWindow("Video") cv.NamedWindow("Results") # iterate through each frames of the video while (True): frame = cv.QueryFrame(capture) if (not frame): break; frame = cv.CloneImage(frame) cv.Smooth(frame, frame, cv.CV_GAUSSIAN, 3, 3) # smooth the original image using Gaussian kernel if (True): # 赤色領域を検出(3) 重心も計算 # http://d.hatena.ne.jp/shokai/20090203/1233609981 the_size = cv.GetSize(frame) # w = frame.width # h = frame.height imgR = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1) imgG = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1) imgB = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1) imgThreshold_R = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1) imgThreshold_G = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1) imgThreshold_B = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1) imgResult = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1) imgTmp = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1) cv.Split(frame, imgB, imgG, imgR, None) # BGRを分解 # 赤の要素が100以上で、緑と青より1.5倍以上あるピクセルを抽出 cv.Threshold(imgR, imgThreshold_R, 100, 255, cv.CV_THRESH_BINARY) cv.Div(imgR, imgG, imgTmp, 10) # 10倍 cv.Threshold(imgTmp, imgThreshold_G, 15, 255, cv.CV_THRESH_BINARY) cv.Div(imgR, imgB, imgTmp, 10) cv.Threshold(imgTmp, imgThreshold_B, 15, 255, cv.CV_THRESH_BINARY) cv.And(imgThreshold_G, imgThreshold_B, imgTmp, None) cv.And(imgTmp, imgThreshold_R, imgResult, None) # cv.Moments(imgResult, moments, 0) moments = cv.Moments(cv.GetMat(imgResult, 1), 0) m00 = cv.GetSpatialMoment(moments, 0, 0) m10 = cv.GetSpatialMoment(moments, 1, 0) m01 = cv.GetSpatialMoment(moments, 0, 1) if (m00 != 0): gX = int(m10 // m00) gY = int(m01 // m00) # cvCircle(frame, cvPoint(gX, gY), 80, CV_RGB(0,0,255), 6, 8, 0); cv.Circle(frame, (gX, gY), 80, (0, 0, 255), 6, 8, 0) else: # Color Detection & Object Tracking # http://opencv-srf.blogspot.ro/2010/09/object-detection-using-color-seperation.html imgHSV = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 3) cv.CvtColor(frame, imgHSV, cv.CV_BGR2HSV) # Change the color format from BGR to HSV imgResult = GetThresholdedImage(imgHSV) cv.Smooth(imgResult, imgResult, cv.CV_GAUSSIAN, 3, 3) # smooth the binary image using Gaussian kernel cv.ShowImage("Results", imgResult) cv.ShowImage("Video", frame) # Clean up used images # cv.ReleaseImage(imgHSV) # cv.ReleaseImage(imgResult) # cv.ReleaseImage(frame) # Wait 50mS c = cv.WaitKey(10) # If 'ESC' is pressed, break the loop if (c == 0x1b): break cv.DestroyAllWindows() # cv.ReleaseCapture(capture) return 0 if __name__ == '__main__': main()
0 件のコメント:
コメントを投稿