FC2カウンター FPGAの部屋

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Ubuntu 16.04 にOpenCV 3.1.0 をインストールした

白線追従用の画像を処理するためにUbuntu 16.04 にOpenCV 3.1.0 をインストールすることにした。
なお、”Ubuntu 16.04にOpenCV 3.1をインストールする手順”を参考にさせていただいた。

早速、下準備から、
sudo apt-get install build-essential cmake git
Ubuntu_OpenCV_1_170726.png

sudo apt-get install ffmpeg libopencv-dev libgtk-3-dev python-numpy python3-numpy libdc1394-22 libdc1394-22-dev libjpeg-dev libpng12-dev libtiff5-dev libjasper-dev libavcodec-dev libavformat-dev libswscale-dev libxine2-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libv4l-dev libtbb-dev qtbase5-dev libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev x264 v4l-utils unzip
Ubuntu_OpenCV_2_170726.png

wget https://github.com/Itseez/opencv/archive/3.1.0.zip
Ubuntu_OpenCV_3_170726.png

unzip 3.1.0
Ubuntu_OpenCV_4_170726.png

cd opencv-3.1.0
mkdir build
cd build

Ubuntu_OpenCV_5_170726.png

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D WITH_V4L=ON -D WITH_QT=ON -D WITH_OPENGL=ON ..
Ubuntu_OpenCV_6_170726.png

成功した。コンフィギュレーションを貼っておく。

-- General configuration for OpenCV 3.1.0 =====================================
--   Version control:               unknown
-- 
--   Platform:
--     Host:                        Linux 4.4.0-87-generic x86_64
--     CMake:                       3.3.2
--     CMake generator:             Unix Makefiles
--     CMake build tool:            /usr/bin/make
--     Configuration:               RELEASE
-- 
--   C/C++:
--     Built as dynamic libs?:      YES
--     C++ Compiler:                /usr/bin/c++  (ver 5.4.0)
--     C++ flags (Release):         -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wno-narrowing -Wno-delete-non-virtual-dtor -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -msse -msse2 -mno-avx -msse3 -mno-ssse3 -mno-sse4.1 -mno-sse4.2 -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG  -DNDEBUG
--     C++ flags (Debug):           -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wno-narrowing -Wno-delete-non-virtual-dtor -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -msse -msse2 -mno-avx -msse3 -mno-ssse3 -mno-sse4.1 -mno-sse4.2 -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden -g  -O0 -DDEBUG -D_DEBUG
--     C Compiler:                  /usr/bin/cc
--     C flags (Release):           -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wno-narrowing -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -msse -msse2 -mno-avx -msse3 -mno-ssse3 -mno-sse4.1 -mno-sse4.2 -ffunction-sections -fvisibility=hidden -O3 -DNDEBUG  -DNDEBUG
--     C flags (Debug):             -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wno-narrowing -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -msse -msse2 -mno-avx -msse3 -mno-ssse3 -mno-sse4.1 -mno-sse4.2 -ffunction-sections -fvisibility=hidden -g  -O0 -DDEBUG -D_DEBUG
--     Linker flags (Release):
--     Linker flags (Debug):
--     Precompiled headers:         YES
--     Extra dependencies:          Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Test Qt5::Concurrent Qt5::OpenGL /usr/lib/x86_64-linux-gnu/libpng.so /usr/lib/x86_64-linux-gnu/libz.so /usr/lib/x86_64-linux-gnu/libtiff.so /usr/lib/x86_64-linux-gnu/libjasper.so /usr/lib/x86_64-linux-gnu/libjpeg.so /usr/lib/x86_64-linux-gnu/libImath.so /usr/lib/x86_64-linux-gnu/libIlmImf.so /usr/lib/x86_64-linux-gnu/libIex.so /usr/lib/x86_64-linux-gnu/libHalf.so /usr/lib/x86_64-linux-gnu/libIlmThread.so gstvideo-1.0 gstapp-1.0 gstbase-1.0 gstriff-1.0 gstpbutils-1.0 gstreamer-1.0 gobject-2.0 glib-2.0 dc1394 v4l1 v4l2 avcodec-ffmpeg avformat-ffmpeg avutil-ffmpeg swscale-ffmpeg dl m pthread rt /usr/lib/x86_64-linux-gnu/libGLU.so /usr/lib/x86_64-linux-gnu/libGL.so tbb atomic cudart nppc nppi npps cufft -L/usr/local/cuda/lib64
--     3rdparty dependencies:       libwebp
-- 
--   OpenCV modules:
--     To be built:                 cudev core cudaarithm flann imgproc ml video cudabgsegm cudafilters cudaimgproc cudawarping imgcodecs photo shape videoio cudacodec highgui objdetect ts features2d calib3d cudafeatures2d cudalegacy cudaobjdetect cudaoptflow cudastereo stitching superres videostab python2
--     Disabled:                    world
--     Disabled by dependency:      -
--     Unavailable:                 java python3 viz
-- 
--   GUI: 
--     QT 5.x:                      YES (ver 5.5.1)
--     QT OpenGL support:           YES (Qt5::OpenGL 5.5.1)
--     OpenGL support:              YES (/usr/lib/x86_64-linux-gnu/libGLU.so /usr/lib/x86_64-linux-gnu/libGL.so)
--     VTK support:                 NO
-- 
--   Media I/O: 
--     ZLib:                        /usr/lib/x86_64-linux-gnu/libz.so (ver 1.2.8)
--     JPEG:                        /usr/lib/x86_64-linux-gnu/libjpeg.so (ver )
--     WEBP:                        build (ver 0.3.1)
--     PNG:                         /usr/lib/x86_64-linux-gnu/libpng.so (ver 1.2.54)
--     TIFF:                        /usr/lib/x86_64-linux-gnu/libtiff.so (ver 42 - 4.0.6)
--     JPEG 2000:                   /usr/lib/x86_64-linux-gnu/libjasper.so (ver 1.900.1)
--     OpenEXR:                     /usr/lib/x86_64-linux-gnu/libImath.so /usr/lib/x86_64-linux-gnu/libIlmImf.so /usr/lib/x86_64-linux-gnu/libIex.so /usr/lib/x86_64-linux-gnu/libHalf.so /usr/lib/x86_64-linux-gnu/libIlmThread.so (ver 2.2.0)
--     GDAL:                        NO
-- 
--   Video I/O:
--     DC1394 1.x:                  NO
--     DC1394 2.x:                  YES (ver 2.2.4)
--     FFMPEG:                      YES
--       codec:                     YES (ver 56.60.100)
--       format:                    YES (ver 56.40.101)
--       util:                      YES (ver 54.31.100)
--       swscale:                   YES (ver 3.1.101)
--       resample:                  NO
--       gentoo-style:              YES
--     GStreamer:                   
--       base:                      YES (ver 1.8.3)
--       video:                     YES (ver 1.8.3)
--       app:                       YES (ver 1.8.3)
--       riff:                      YES (ver 1.8.3)
--       pbutils:                   YES (ver 1.8.3)
--     OpenNI:                      NO
--     OpenNI PrimeSensor Modules:  NO
--     OpenNI2:                     NO
--     PvAPI:                       NO
--     GigEVisionSDK:               NO
--     UniCap:                      NO
--     UniCap ucil:                 NO
--     V4L/V4L2:                    Using libv4l1 (ver 1.10.0) / libv4l2 (ver 1.10.0)
--     XIMEA:                       NO
--     Xine:                        NO
--     gPhoto2:                     NO
-- 
--   Parallel framework:            TBB (ver 4.4 interface 9002)
-- 
--   Other third-party libraries:
--     Use IPP:                     9.0.1 [9.0.1]
--          at:                     /home/masaaki/opencv-3.1.0/3rdparty/ippicv/unpack/ippicv_lnx
--     Use IPP Async:               NO
--     Use VA:                      NO
--     Use Intel VA-API/OpenCL:     NO
--     Use Eigen:                   NO
--     Use Cuda:                    YES (ver 8.0)
--     Use OpenCL:                  YES
--     Use custom HAL:              NO
-- 
--   NVIDIA CUDA
--     Use CUFFT:                   YES
--     Use CUBLAS:                  NO
--     USE NVCUVID:                 NO
--     NVIDIA GPU arch:             20 21 30 35
--     NVIDIA PTX archs:            30
--     Use fast math:               NO
-- 
--   OpenCL:
--     Version:                     dynamic
--     Include path:                /home/masaaki/opencv-3.1.0/3rdparty/include/opencl/1.2
--     Use AMDFFT:                  NO
--     Use AMDBLAS:                 NO
-- 
--   Python 2:
--     Interpreter:                 /usr/bin/python2.7 (ver 2.7.12)
--     Libraries:                   /usr/lib/x86_64-linux-gnu/libpython2.7.so (ver 2.7.12)
--     numpy:                       /home/masaaki/.local/lib/python2.7/site-packages/numpy/core/include (ver 1.11.0)
--     packages path:               lib/python2.7/dist-packages
-- 
--   Python 3:
--     Interpreter:                 /usr/bin/python3 (ver 3.5.2)
-- 
--   Python (for build):            /usr/bin/python2.7
-- 
--   Java:
--     ant:                         NO
--     JNI:                         NO
--     Java wrappers:               NO
--     Java tests:                  NO
-- 
--   Matlab:                        Matlab not found or implicitly disabled
-- 
--   Documentation:
--     Doxygen:                     NO
--     PlantUML:                    NO
-- 
--   Tests and samples:
--     Tests:                       YES
--     Performance tests:           YES
--     C/C++ Examples:              NO
-- 
--   Install path:                  /usr/local
-- 
--   cvconfig.h is in:              /home/masaaki/opencv-3.1.0/build
-- -----------------------------------------------------------------
-- 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/masaaki/opencv-3.1.0/build


make
Ubuntu_OpenCV_7_170726.png

エラーになってしまった。エラー内容を示す。

/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:120:54: error: ‘NppiGraphcutState’ has not been declared
     typedef NppStatus (*init_func_t)(NppiSize oSize, NppiGraphcutState** ppStat
                                                      ^
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:135:18: error: ‘NppiGraphcutState’ does not name a type
         operator NppiGraphcutState*()
                  ^
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:141:9: error: ‘NppiGraphcutState’ does not name a type
         NppiGraphcutState* pState;
         ^
In file included from /home/masaaki/opencv-3.1.0/build/modules/cudalegacy/precomp.hpp:75:0:
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp: In constructor ‘{anonymous}::NppiGraphcutStateHandler::NppiGraphcutStateHandler(NppiSize, Npp8u*, {anonymous}::init_func_t)’:
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:127:39: error: ‘pState’ was not declared in this scope
             nppSafeCall( func(sznpp, &pState, pDeviceMem) );
                                       ^
/home/masaaki/opencv-3.1.0/modules/core/include/opencv2/core/private.cuda.hpp:165:52: note: in definition of macro ‘nppSafeCall’
 #define nppSafeCall(expr)  cv::cuda::checkNppError(expr, __FILE__, __LINE__, CV
                                                    ^
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp: In destructor ‘{anonymous}::NppiGraphcutStateHandler::~NppiGraphcutStateHandler()’:
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:132:43: error: ‘pState’ was not declared in this scope
             nppSafeCall( nppiGraphcutFree(pState) );
                                           ^
/home/masaaki/opencv-3.1.0/modules/core/include/opencv2/core/private.cuda.hpp:165:52: note: in definition of macro ‘nppSafeCall’
 #define nppSafeCall(expr)  cv::cuda::checkNppError(expr, __FILE__, __LINE__, CV
                                                    ^
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:132:49: error: ‘nppiGraphcutFree’ was not declared in this scope
             nppSafeCall( nppiGraphcutFree(pState) );
                                                 ^
/home/masaaki/opencv-3.1.0/modules/core/include/opencv2/core/private.cuda.hpp:165:52: note: in definition of macro ‘nppSafeCall’
 #define nppSafeCall(expr)  cv::cuda::checkNppError(expr, __FILE__, __LINE__, CV
                                                    ^
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp: In function ‘void cv::cuda::graphcut(cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::Stream&)’:
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:174:51: error: ‘nppiGraphcutGetSize’ was not declared in this scope
     nppSafeCall( nppiGraphcutGetSize(sznpp, &bufsz) );
                                                   ^
/home/masaaki/opencv-3.1.0/modules/core/include/opencv2/core/private.cuda.hpp:165:52: note: in definition of macro ‘nppSafeCall’
 #define nppSafeCall(expr)  cv::cuda::checkNppError(expr, __FILE__, __LINE__, CV
                                                    ^
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:182:61: error: ‘nppiGraphcutInitAlloc’ was not declared in this scope
     NppiGraphcutStateHandler state(sznpp, buf.ptr<Npp8u>(), nppiGraphcutInitAll
                                                             ^
In file included from /home/masaaki/opencv-3.1.0/build/modules/cudalegacy/precomp.hpp:75:0:
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:191:146: error: ‘nppiGraphcut_32s8u’ was not declared in this scope
 nsp.step), sznpp, labels.ptr<Npp8u>(), static_cast<int>(labels.step), state) );
                                                                            ^
/home/masaaki/opencv-3.1.0/modules/core/include/opencv2/core/private.cuda.hpp:165:52: note: in definition of macro ‘nppSafeCall’
 #define nppSafeCall(expr)  cv::cuda::checkNppError(expr, __FILE__, __LINE__, CV
                                                    ^
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:196:146: error: ‘nppiGraphcut_32f8u’ was not declared in this scope
 nsp.step), sznpp, labels.ptr<Npp8u>(), static_cast<int>(labels.step), state) );
                                                                            ^
/home/masaaki/opencv-3.1.0/modules/core/include/opencv2/core/private.cuda.hpp:165:52: note: in definition of macro ‘nppSafeCall’
 #define nppSafeCall(expr)  cv::cuda::checkNppError(expr, __FILE__, __LINE__, CV
                                                    ^
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp: In function ‘void cv::cuda::graphcut(cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::GpuMat&, cv::cuda::Stream&)’:
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:246:52: error: ‘nppiGraphcut8GetSize’ was not declared in this scope
     nppSafeCall( nppiGraphcut8GetSize(sznpp, &bufsz) );
                                                    ^
/home/masaaki/opencv-3.1.0/modules/core/include/opencv2/core/private.cuda.hpp:165:52: note: in definition of macro ‘nppSafeCall’
 #define nppSafeCall(expr)  cv::cuda::checkNppError(expr, __FILE__, __LINE__, CV
                                                    ^
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:254:61: error: ‘nppiGraphcut8InitAlloc’ was not declared in this scope
     NppiGraphcutStateHandler state(sznpp, buf.ptr<Npp8u>(), nppiGraphcut8InitAl
                                                             ^
In file included from /home/masaaki/opencv-3.1.0/build/modules/cudalegacy/precomp.hpp:75:0:
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:267:146: error: ‘nppiGraphcut8_32s8u’ was not declared in this scope
 nsp.step), sznpp, labels.ptr<Npp8u>(), static_cast<int>(labels.step), state) );
                                                                            ^
/home/masaaki/opencv-3.1.0/modules/core/include/opencv2/core/private.cuda.hpp:165:52: note: in definition of macro ‘nppSafeCall’
 #define nppSafeCall(expr)  cv::cuda::checkNppError(expr, __FILE__, __LINE__, CV
                                                    ^
/home/masaaki/opencv-3.1.0/modules/cudalegacy/src/graphcuts.cpp:274:146: error: ‘nppiGraphcut8_32f8u’ was not declared in this scope
 nsp.step), sznpp, labels.ptr<Npp8u>(), static_cast<int>(labels.step), state) );
                                                                            ^
/home/masaaki/opencv-3.1.0/modules/core/include/opencv2/core/private.cuda.hpp:165:52: note: in definition of macro ‘nppSafeCall’
 #define nppSafeCall(expr)  cv::cuda::checkNppError(expr, __FILE__, __LINE__, CV
                                                    ^
modules/cudalegacy/CMakeFiles/opencv_cudalegacy.dir/build.make:362: ターゲット 'modules/cudalegacy/CMakeFiles/opencv_cudalegacy.dir/src/graphcuts.cpp.o' のレシピで失敗しました
make[2]: *** [modules/cudalegacy/CMakeFiles/opencv_cudalegacy.dir/src/graphcuts.cpp.o] エラー 1
CMakeFiles/Makefile2:9285: ターゲット 'modules/cudalegacy/CMakeFiles/opencv_cudalegacy.dir/all' のレシピで失敗しました
make[1]: *** [modules/cudalegacy/CMakeFiles/opencv_cudalegacy.dir/all] エラー 2
Makefile:160: ターゲット 'all' のレシピで失敗しました
make: *** [all] エラー 2


どうやらCUDA 関係のエラーのようだ。
opencv3.10 does not support cuda8.0rc? #6677”とかを見ていろいろとやってみたが、うまく行かなかった。
ツィッターでdandelion さんから、「CUDA8だと一部モジュールがビルドできない問題があります。OpenCV 3.2で修正されてます。」と教えて頂いた。
よって、OpenCV 3.2 以降をインストールすることにした。
  1. 2017年07月28日 04:29 |
  2. OpenCV
  3. | トラックバック:0
  4. | コメント:0

家の2階にLANを通しました

家の2階が無線LANが弱いので、PLCアダプタを買って2階にLANを通しました。
PLCアダプタは「TP-Link PLCアダプター パワーライン インターネット接続 有線LAN コンセントLAN 2台キット 総務省指定 TL-PA4010 KIT」です。リンクするためにペアボタンを押しても、なかなかLEDが点滅してくれなくて焦りましたが、リセットしたら点滅してくれました。その後のリンクはすぐできました。結構安定しているし、スピードも計測はしていないですが、速いです。
2 階のPLCアダプタには、「BUFFALO 11ac/n/a/g/b 無線LAN親機(Wi-Fiルーター) ビームフォーミング対応 866+300Mbps WHR-1166DHP4」をつけました。これはブリッジモードで無線LANアクセスポイントとして使用しています。これでお手軽に2階の無線LAN環境が構築できました。
ちなみに、家では、NTTのフレッツ光に、Yahoo BBルータ+BBフォンのルーター機能を使っています。その下に1階はブリッジモードのロジテックの無線LANルータを使用しています。
  1. 2017年07月28日 03:58 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

HLS ビデオライブラリの hls::Window のVivado HLS 2015.4 以前とその後での変更点3(ソースコード)

HLS ビデオライブラリの hls::LineBuffer のVivado HLS 2015.4 以前とその後での変更点1(メモリ・ライン・バッファー)
HLS ビデオライブラリの hls::Window のVivado HLS 2015.4 以前とその後での変更点2(メモリ・ウインドウ・バッファー)
でメモリ・ライン・バッファーとメモリ・ウインドウ・バッファーのVivado HLS 2015.4 以前と以後の変更点を説明してきた。
今回は、ソースコードを貼っておこうと思う。Vivado HLSのソースコードはVivado HLS 2016.1 以降のメモリ・ライン・バッファーとメモリ・ウインドウ・バッファーのメソッドを使用している。それに対して、テストベンチはVivado HLS 2015.4 以前のメソッドを使用しているので、比べてみてほしい。
なお、これらのコードはガボール・フィルタのプロジェクトを使用している。

まずは、CソースコードのGabor_fiter_lh.cpp から貼っておく。

// Gabor_fiter_lh.cpp
// 2016/07/23 by marsee
// 2016/07/25 : 右白線検出用のGabor Filterを追加して、右左の白線を指定するRorL 引数を追加
// 2016/07/27 : 右白線検出用配列と左白線検出用配列を統合
//

#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <hls_video.h>

#include "Gabor_filter_lh.h"

int conv_rgb2y(int rgb);

int Gabor_filter_lh(hls::stream<ap_axis<32,1,1,1> >& ins,
        hls::stream<ap_axis<32,1,1,1> >& outs, ap_uint<1> & RorL){
#pragma HLS INTERFACE ap_none port=RorL
#pragma HLS INTERFACE axis port=ins
#pragma HLS INTERFACE axis port=outs
#pragma HLS INTERFACE s_axilite port=return

    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> gabor;

    hls::LineBuffer<ARRAY_SIZE-1, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
    hls::Window<ARRAY_SIZE, ARRAY_SIZE, int> mbuf;

    int gray_pix, val, i, j, x, y;

    do {
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
    // user が 1になった時にフレームがスタートする
        ins >> pix;
    } while(pix.user == 0);

    for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
        for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS PIPELINE II=1
            if (!(x==0 && y==0))    // 最初の入力はすでに入力されている
                ins >> pix;    // AXI4-Stream からの入力

            mbuf.shift_pixels_left();    // mbuf の列を1ビット左シフト
            for(i=0; i<ARRAY_SIZE-1; i++){
                mbuf.insert_pixel(linebuf.getval(i,x), i, ARRAY_SIZE-1);
            }
            gray_pix = conv_rgb2y(pix.data);
            mbuf.insert_pixel(gray_pix, ARRAY_SIZE-1, ARRAY_SIZE-1);

            // LineBuffer の更新
            linebuf.shift_pixels_up(x);
            linebuf.insert_bottom_row(gray_pix, x);

            // Gabor filter の演算
            for (j=0, val=0; j<ARRAY_SIZE-1; j++){
                for (i=0; i<ARRAY_SIZE-1; i++){
                    val += gabor_weight[(int)RorL][j][i] * mbuf(j,i);
                }
            }
            val = val/256// 256倍してあるので、1/256して戻す
            if (val<0)
                //val = -val; // 絶対値
                val = 0// マイナスの値を0に丸める
            else if (val>255)
                val = 255;

            // Gabor filter・データの書き込み
            gabor.data = (val<<16)+(val<<8)+val;
            // 最初のARRAY_SIZE-1行とその他の行の最初のARRAY_SIZE-1列は無効データなので0とする
            if (x<(ARRAY_SIZE-1) || y<(ARRAY_SIZE-1))
                gabor.data = 0;

            if (x==0 && y==0// 最初のデータでは、TUSERをアサートする
                gabor.user = 1;
            else
                gabor.user = 0;

            if (x == (HORIZONTAL_PIXEL_WIDTH-1))    // 行の最後で TLAST をアサートする
                gabor.last = 1;
            else
                gabor.last = 0;

            outs << gabor;    // AXI4-Stream へ出力
         }
     }
     return(0);
}

// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
    int r, g, b, y_f;
    int y;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8// 256で割る

    return(y);
}


次に、テストベンチのGabor_filter_lh_tb.cpp を貼っておく。なお、メモリ・ライン・バッファーとメモリ・ウインドウ・バッファーのVivado HLS 2015.4 以前のコードが書いてある関数は、Gabor_filter_lh_soft() だ。

// Gabor_filter_lh_tb.cpp
// 2016/07/24 by marsee
// 2016/07/25 : 右白線検出用のGabor Filterを追加して、右左の白線を指定するRorL 引数を追加
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include <ap_axi_sdata.h>
#include <hls_video.h>

#include "Gabor_filter_lh.h"
#include "bmp_header.h"

int Gabor_filter_lh(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, ap_uint<1> & RorL);

int conv_rgb2y_soft(int rgb);
int Gabor_filter_lh_soft(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, ap_uint<1> & RorL);

#define CLOCK_PERIOD 10
#define RIGHT_OR_LEFT  LEFT_WEIGHT
#define BMP_FILE_NAME   "bmp_f_0823_0.bmp"

int main()
{
    using namespace std;

    hls::stream<ap_axis<32,1,1,1> > ins;
    hls::stream<ap_axis<32,1,1,1> > ins_soft;
    hls::stream<ap_axis<32,1,1,1> > outs;
    hls::stream<ap_axis<32,1,1,1> > outs_soft;
    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> vals;
    ap_axis<32,1,1,1> vals_soft;

    int m_seq = 1// M系列の値
    int i;
    int xor_shift;

    BITMAPFILEHEADER bmpfhr; // BMPファイルのファイルヘッダ(for Read)
    BITMAPINFOHEADER bmpihr; // BMPファイルのINFOヘッダ(for Read)
    FILE *fbmpr, *fbmpw, *fbmpwf;
    int *rd_bmp, *hw_gabor, *sw_gabor;
    int blue, green, red;
    ap_uint<1> r_l;

    if ((fbmpr = fopen(BMP_FILE_NAME, "rb")) == NULL){ // test.bmp をオープン
        fprintf(stderr, "Can't open test.bmp by binary read mode\n");
        exit(1);
    }
    // bmpヘッダの読み出し
    fread(&bmpfhr.bfType, sizeof(char), 2, fbmpr);
    fread(&bmpfhr.bfSize, sizeof(long), 1, fbmpr);
    fread(&bmpfhr.bfReserved1, sizeof(short), 1, fbmpr);
    fread(&bmpfhr.bfReserved2, sizeof(short), 1, fbmpr);
    fread(&bmpfhr.bfOffBits, sizeof(long), 1, fbmpr);
    fread(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpr);

    // ピクセルを入れるメモリをアロケートする
    if ((rd_bmp =(int *)malloc(sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
        fprintf(stderr, "Can't allocate rd_bmp memory\n");
        exit(1);
    }
    if ((hw_gabor =(int *)malloc(sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
        fprintf(stderr, "Can't allocate hw_gabor memory\n");
        exit(1);
    }
    if ((sw_gabor =(int *)malloc(sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
        fprintf(stderr, "Can't allocate hw_gabor memory\n");
        exit(1);
    }

    // rd_bmp にBMPのピクセルを代入。その際に、行を逆転する必要がある
    for (int y=0; y<bmpihr.biHeight; y++){
        for (int x=0; x<bmpihr.biWidth; x++){
            blue = fgetc(fbmpr);
            green = fgetc(fbmpr);
            red = fgetc(fbmpr);
            rd_bmp[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] = (blue & 0xff) | ((green & 0xff)<<8) | ((red & 0xff)<<16);
        }
    }
    fclose(fbmpr);

    // ins に入力データを用意する
    for(int i=0; i<5; i++){    // dummy data
        pix.user = 0;
        pix.data = i;
        ins << pix;
    }

    for(int j=0; j < bmpihr.biHeight; j++){
        for(i=0; i < bmpihr.biWidth; i++){
            pix.data = (ap_int<32>)rd_bmp[(j*bmpihr.biWidth)+i];

            if (j==0 && i==0)    // 最初のデータの時に TUSER を 1 にする
                pix.user = 1;
            else
                pix.user = 0;

            if (i == bmpihr.biWidth-1// 行の最後でTLASTをアサートする
                pix.last = 1;
            else
                pix.last = 0;

            ins << pix;
            ins_soft << pix;
        }
    }

    r_l = (ap_uint<1>)RIGHT_OR_LEFT;
    Gabor_filter_lh(ins, outs, r_l);
    Gabor_filter_lh_soft(ins_soft, outs_soft, r_l);

    // ハードウェアとソフトウェアのラプラシアン・フィルタの値のチェック
    cout << endl;
    cout << "outs" << endl;
    for(int j=0; j < bmpihr.biHeight; j++){
        for(i=0; i < bmpihr.biWidth; i++){
            outs >> vals;
            outs_soft >> vals_soft;
            ap_int<32> val = vals.data;
            ap_int<32> val_soft = vals_soft.data;

            hw_gabor[(j*bmpihr.biWidth)+i] = (int)val;
            sw_gabor[(j*bmpihr.biWidth)+i] = (int)val_soft;

            if ((double)pow((double)(val&0xff)-(val_soft&0xff),(double)2) > 4){ // 2乗誤差が4よりも大きい
                printf("ERROR HW and SW results mismatch i = %ld, j = %ld, HW = %08x, SW = %08x\n", i, j, (int)val, (int)val_soft);
                //return(1);
            }
            //if (vals.last)
                //cout << "AXI-Stream is end" << endl;
        }
    }
    cout << "Success HW and SW results match" << endl;
    cout << endl;

    // ハードウェアのラプラシアンフィルタの結果を temp_gabor.bmp へ出力する
    if ((fbmpw=fopen("temp_gabor.bmp""wb")) == NULL){
        fprintf(stderr, "Can't open temp_gabor.bmp by binary write mode\n");
        exit(1);
    }
    // BMPファイルヘッダの書き込み
    fwrite(&bmpfhr.bfType, sizeof(char), 2, fbmpw);
    fwrite(&bmpfhr.bfSize, sizeof(long), 1, fbmpw);
    fwrite(&bmpfhr.bfReserved1, sizeof(short), 1, fbmpw);
    fwrite(&bmpfhr.bfReserved2, sizeof(short), 1, fbmpw);
    fwrite(&bmpfhr.bfOffBits, sizeof(long), 1, fbmpw);
    fwrite(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpw);
    // RGB データの書き込み、逆順にする
    for (int y=0; y<bmpihr.biHeight; y++){
        for (int x=0; x<bmpihr.biWidth; x++){
            blue = hw_gabor[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] & 0xff;
            green = (hw_gabor[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] >> 8) & 0xff;
            red = (hw_gabor[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x]>>16) & 0xff;

            fputc(blue, fbmpw);
            fputc(green, fbmpw);
            fputc(red, fbmpw);
        }
    }
    fclose(fbmpw);

    // ソフトウェアのラプラシアンフィルタの結果を temp_gabor_float.bmp へ出力する
    if ((fbmpwf=fopen("temp_gabor_float.bmp""wb")) == NULL){
        fprintf(stderr, "Can't open temp_gabor_float.bmp by binary write mode\n");
        exit(1);
    }
    // BMPファイルヘッダの書き込み
    fwrite(&bmpfhr.bfType, sizeof(char), 2, fbmpwf);
    fwrite(&bmpfhr.bfSize, sizeof(long), 1, fbmpwf);
    fwrite(&bmpfhr.bfReserved1, sizeof(short), 1, fbmpwf);
    fwrite(&bmpfhr.bfReserved2, sizeof(short), 1, fbmpwf);
    fwrite(&bmpfhr.bfOffBits, sizeof(long), 1, fbmpwf);
    fwrite(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpwf);
    // RGB データの書き込み、逆順にする
    for (int y=0; y<bmpihr.biHeight; y++){
        for (int x=0; x<bmpihr.biWidth; x++){
            blue = sw_gabor[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] & 0xff;
            green = (sw_gabor[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] >> 8) & 0xff;
            red = (sw_gabor[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x]>>16) & 0xff;

            fputc(blue, fbmpwf);
            fputc(green, fbmpwf);
            fputc(red, fbmpwf);
        }
    }
    fclose(fbmpwf);

    free(rd_bmp);
    free(hw_gabor);

    return 0;
}

int Gabor_filter_lh_soft(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, ap_uint<1> & RorL){
    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> gabor;

    hls::LineBuffer<ARRAY_SIZE-1, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
    hls::Window<ARRAY_SIZE, ARRAY_SIZE, int> mbuf;

    int gray_pix, val, i, j, x, y;
    float valf;

    do {    // user が 1になった時にフレームがスタートする
        ins >> pix;
    } while(pix.user == 0);

    for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
        for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
            if (!(x==0 && y==0))    // 最初の入力はすでに入力されている
                ins >> pix;    // AXI4-Stream からの入力

            mbuf.shift_left();    // mbuf の列を1ビット左シフト
            for(i=ARRAY_SIZE-2; i>=0; --i){
                mbuf.insert(linebuf(i,x), i+1, ARRAY_SIZE-1);
            }
            gray_pix = conv_rgb2y_soft(pix.data);
            mbuf.insert(gray_pix, 0, ARRAY_SIZE-1);

            // LineBuffer の更新
            linebuf.shift_down(x);
            linebuf.insert_bottom(gray_pix, x);

            // Gabor filter の演算
            for (j=0, valf=0; j<ARRAY_SIZE-1; j++){
                for (i=0; i<ARRAY_SIZE-1; i++){
                    valf += gabor_fweight[(int)RorL][j][i] * (float)mbuf(ARRAY_SIZE-1-j,i);
                }
            }

            val = (int)valf;
            if (val<0)
                //val = -val; // 絶対値
                val = 0// マイナスの値を0に丸める
            else if (val>255)
                val = 255;

            // Gabor filter・データの書き込み
            gabor.data = (val<<16)+(val<<8)+val;
            // 最初のARRAY_SIZE-1行とその他の行の最初のARRAY_SIZE-1列は無効データなので0とする
            if (x<(ARRAY_SIZE-1) || y<(ARRAY_SIZE-1))
                gabor.data = 0;

            if (x==0 && y==0// 最初のデータでは、TUSERをアサートする
                gabor.user = 1;
            else
                gabor.user = 0;

            if (x == (HORIZONTAL_PIXEL_WIDTH-1))    // 行の最後で TLAST をアサートする
                gabor.last = 1;
            else
                gabor.last = 0;

            outs << gabor;    // AXI4-Stream へ出力
         }
     }
     return(0);
}

// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y_soft(int rgb){
    int r, g, b, y_f;
    int y;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8// 256で割る

    return(y);
}

  1. 2017年07月27日 05:34 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

HLS ビデオライブラリの hls::Window のVivado HLS 2015.4 以前とその後での変更点2(メモリ・ウインドウ・バッファー)

HLS ビデオライブラリの hls::LineBuffer のVivado HLS 2015.4 以前とその後での変更点”の続き。

hls::LineBuffer と同様に、hls::Window も行のインデックスとクラス・メソッドが変更になっているので紹介する。
hls::LineBuffer と同様に、hls::Window もガボール・フィルタでカーネルとして、重みとの演算に使用されている。

Vivado HLS 2015.4 以前のメモリ・ウインドウのデータ セットを引用する。”Vivado Design Suite ユーザー ガイド 高位合成 UG902 (v2015.4) 2015 年 11 月 24 日”の”メモリ・ウインドウ・バッファー”の 194 ページの”表 2‐10 : メモリ ウ ィ ン ド ウ例のデー タ セッ ト”を引用する。
gabor_filter_lh2_3_170725.png

やはり、行が行2 から始まって、行1 、行0 とインデックスが減っているのが分かるだろうか?列は列0 から始まって増えていっている。メモリ・ウインドウを更新する際には、shift_left() メソッドでメモリ・ウインドウを1ビット左シフトし、insert()メソッドで、インデック0 以外にメモリ・ライン・バッファーの値を入力し、インデック0 には、現在の画像ピクセルの値を入力した。つまり、通常と逆のインデックスになっている。ソースコードを示す。

            mbuf.shift_left();    // mbuf の列を1ビット左シフト
            for(i=ARRAY_SIZE-2; i>=0; --i){
                mbuf.insert(linebuf(i,x), i+1, ARRAY_SIZE-1);
            }
            gray_pix = conv_rgb2y_soft(pix.data);
            mbuf.insert(gray_pix, 0, ARRAY_SIZE-1);


前回同様に、Vivado HLS 2016.1 からは、この行のインデックスが通常と同様にインデックス 0 からとなっている。
下に、”Vivado Design Suite ユーザー ガイド 高位合成 UG902 (v2017.1) 2017 年 4 月 5 日”の”HLS ビデオライブラリ”の”メモリ ウィンドウ バッファー ”の221 ページの”2‐9: メモリ ウ ィ ン ド ウ例のデー タ セット”を引用する。
gabor_filter_lh2_4_170725.png

行のインデックスが列のインデックス同様に 0 から始まっているのが分かると思う。メモリ・ウインドウ・バッファーのメソッドも更新されている。メモリ・ウインドウ・バッファーのメソッドを示す。

• shift_pixels_up()
• shift_pixels_down()
• shift_pixels_left()
• shift_pixels_right()
• insert_pixel(value,row,colum)
• insert_row()
• insert_bottom_row()
• insert_top_row()
• insert_col()
• insert_left_col()
• insert_right_col()
• getval(row, column)


やはり、今まで使用していたshifft_left(), insert() が無くなっている。前回同様、互換性確保のためにshifft_left(), insert() メソッドなどの、Vivado HLS 2015.4 以前のコードも使用することができた。Vivado HLS 2016.1 以降の新しいメソッドを使用して、同様にメモリ・ウインドウの処理をする場合には、shift_pixels_left() と insert_pixel() を使用する。
新しいメソッドを使用した上と同様のコードを示す。

            mbuf.shift_pixels_left();    // mbuf の列を1ビット左シフト
            for(i=0; i<ARRAY_SIZE-1; i++){
                mbuf.insert_pixel(linebuf.getval(i,x), i, ARRAY_SIZE-1);
            }
            gray_pix = conv_rgb2y(pix.data);
            mbuf.insert_pixel(gray_pix, ARRAY_SIZE-1, ARRAY_SIZE-1);

  1. 2017年07月26日 05:00 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

HLS ビデオライブラリの hls::LineBuffer のVivado HLS 2015.4 以前とその後での変更点1(メモリ・ライン・バッファー)

ガボール・フィルタ (Gabor Filter) による白線検出5(hls::LineBuffer と hls::Window を使用2)”などで、Vivado HLS のHLS ビデオライブラリのhls::LineBuffer と hls::Window を使用してガボール・フィルタを実装した。

この時は知らなかったが、Vivado HLS 2016.1 から hls::LineBuffer と hls::Window のクラス・メソッドが大きく変更になった。Vivado HLS 2015.4 までは、 hls::LineBuffer と hls::Window の配列の並びは、列はインデックス 0 からなのだが、行はインデックス「行の配列の最大数」かになっていた。”Vivado Design Suite ユーザー ガイド 高位合成 UG902 (v2015.4) 2015 年 11 月 24 日”の”メモリ・ライン・バッファー”の193 ページの”表 2‐7 : LineBuffer 例のデー タ セッ ト”を引用する。
gabor_filter_lh2_1_170725.png

行が行2 から始まって、行1 、行0 とインデックスが減っているのが分かるだろうか?列は列0 から始まって増えていっている。
メモリ・ライン・バッファーの値を更新するためにメモリ・ライン・バッファーの現在処理している列を上方向にシフトするのだが、Vivado HLS 2015.4 まででは、shift_down() メソッドを使用する。とっても紛らわしい。その後、現在のピクセル値を挿入するには、insert_bottom() メソッドを使用する。

Vivado HLS 2016.1 からは、この行のインデックスが通常と同様にインデックス 0 からとなっている。
下に、”Vivado Design Suite ユーザー ガイド 高位合成 UG902 (v2017.1) 2017 年 4 月 5 日”の”HLS ビデオライブラリ”の ” 2‐6: LineBuffer 例のデー タ セッ ト”を引用する。
gabor_filter_lh2_2_170725.png

行のインデックスが列のインデックス同様に 0 から始まっているのが分かると思う。
メモリ・ライン・バッファーのメソッドも更新されている。下に、メモリ・ライン・バッファーのメソッドを示す。

• shift_pixels_up()
• shift_pixels_down()
• insert_bottom_row()
• insert_top_row()
• getval(row,column)


上に示すように、今まで使用していた shift_down() メソッドが無くなっている。ただし、互換性確保のためにshift_down() メソッドというか、Vivado HLS 2015.4 以前のコードも使用することができた。
Vivado HLS 2015.4 以前のコードをVivado HLS 2016.1 以降のコードに書き直すと、shift_pixels_up() メソッドで現在処理している列を上方向にシフトし、insert_bottom_row() で現在のピクセル値を挿入する。
  1. 2017年07月25日 04:47 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作1(概要)

MNIST手書き数字認識用ニューラルネットワークが完成したので、今度は本命のミニ・ロボットカーを白線間を走らせるための白線追従走行用畳み込みニューラルネットワーク(白線追従走行用CNN)を製作しよう。

白線追従走行用CNNを作るにあたって、最初は直線の白線間を追従走行するための畳み込みニューラルネットワーク(CNN)を作ろうと思う。具体的には、多少外れた位置にいても、直線の白線間に戻れるCNNを学習させようと思っている。まずは小手調べとして、直線を走行するためだけのCNNを学習させてみよう。とは言っても外れた場合も戻ってくるように異常状態を考えるといくらでもありそうだ。しかし、ある程度のシチュエーションで白線間に戻れるようにすれば良いかと思うので、そうしようと思う。白線が全く見えない状況で探索する必要は無いということだ。

具体的には、Zybot のカメラで撮影した写真を使って、どの程度の画像サイズでやってみるかを検討してみよう。
カメラで撮影した白線の様子を示す。サムネイルを示すが、真っ直ぐ、右旋回が必要、左旋回が必要な画像に分けてある。
wlt_cnn_5_170723.jpg

画像サイズは 800 x 600 ピクセルだ。なお、白線は塗装コンパネの上に白線を引いてある。すぐに撤去できるようにするためのアイデアなのだが、黄色は結構明るい色なので、心配だ。
これをPaint.net を使用して、試しに加工してみることにした。
wlt_cnn_1_170723.jpg

まずは、20分の1 に縮小してみた。サイズは、40 x 30 だ。
wlt_cnn_2_170723.jpg

白線の引かれている下 1/3 を切り取ってみよう。(画像サイズは 40 x 10 ピクセル)
wlt_cnn_3_170723.jpg

そして、これを白黒画像にする。
wlt_cnn_4_170723.jpg

これで 40 x 10 ピクセルの白線の画像ができた。これでデータセットを作って、学習させてみよう。とりあえず、30枚しかないので、状況を見て、1~数ピクセルを x または y 方向にずらした画像を追加してみよう。あまり画像を回転をすると、曲がらなければならない画像と一致してしまうかもしれない?なかなか難しそうだ。。。
  1. 2017年07月23日 11:19 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

ルンバ622を買いました

ロボット掃除機のiRobot のルンバ622 を買いました。追加 5年保証(落下・水没にも対応) も付けました。

なかなか掃除ができないので、いない間にお掃除してくれるととっても良いからです。

箱です。
Roomba_1_170723.jpg

箱の中身です。リモコンは取り出しちゃったので、入れておきました。
Roomba_2_170723.jpg

ルンバを取り出して、裏を撮りました。
Roomba_3_170723.jpg

表です。
Roomba_4_170723.jpg

ステーションを設置して、充電されているようなので、早速掃除をしてもらいました。
けなげに頑張ってくれています。部屋もきれいになりました。とっても良い物が買えました。値段もお安く買えるようになったんですね。この機能で十分です。


日本のメーカーは何故早くからロボット掃除機を作れなかったんでしょうか?仏壇のろうそくの火問題もあるようですが、解決可能だし仏壇無い家も多いですよね。それに、仏壇はしっかり作ってあるから、たとえろうそく立っていても倒れない気がします?
  1. 2017年07月23日 05:09 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0
»