From c7baf3f624c372194186c8f40f7405ce0d8d9e1a Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Fri, 28 Dec 2018 13:38:46 -0500 Subject: [PATCH 01/22] Update ITK minor version Conflicts: CMake/fletch-tarballs.cmake --- CMake/fletch-tarballs.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMake/fletch-tarballs.cmake b/CMake/fletch-tarballs.cmake index 96373756..291f708e 100644 --- a/CMake/fletch-tarballs.cmake +++ b/CMake/fletch-tarballs.cmake @@ -437,9 +437,9 @@ list(APPEND fletch_external_sources VXL) # ITK set(ITK_version 5.0) -set(ITK_minor b01) -set(ITK_url "https://github.com/InsightSoftwareConsortium/ITK/archive/v${ITK_version}${ITK_minor}.zip") -set(ITK_md5 "3a93ba69d3bf05258054806fab742611") +set(ITK_minor b03) +set(ITK_url "https://github.com/InsightSoftwareConsortium/ITK/archive/${ITK_version}${ITK_minor}.tar.gz") +set(ITK_md5 "84d10e1d6324c1c1250ac4ecfcc1b403") set(ITK_experimental TRUE) list(APPEND fletch_external_sources ITK) From 3a8f940255e0e57df9e9fa7f458ce8a9603d3986 Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Fri, 28 Dec 2018 14:13:46 -0500 Subject: [PATCH 02/22] Update path --- CMake/fletch-tarballs.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/fletch-tarballs.cmake b/CMake/fletch-tarballs.cmake index 291f708e..568e2ef5 100644 --- a/CMake/fletch-tarballs.cmake +++ b/CMake/fletch-tarballs.cmake @@ -438,7 +438,7 @@ list(APPEND fletch_external_sources VXL) # ITK set(ITK_version 5.0) set(ITK_minor b03) -set(ITK_url "https://github.com/InsightSoftwareConsortium/ITK/archive/${ITK_version}${ITK_minor}.tar.gz") +set(ITK_url "https://github.com/InsightSoftwareConsortium/ITK/archive/v${ITK_version}${ITK_minor}.tar.gz") set(ITK_md5 "84d10e1d6324c1c1250ac4ecfcc1b403") set(ITK_experimental TRUE) list(APPEND fletch_external_sources ITK) From 345ea8a3a31173d615b47bf2cb48c5b0db048a1f Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Fri, 28 Dec 2018 14:13:59 -0500 Subject: [PATCH 03/22] Update vxl version Conflicts: CMake/fletch-tarballs.cmake --- CMake/fletch-tarballs.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMake/fletch-tarballs.cmake b/CMake/fletch-tarballs.cmake index 568e2ef5..60895e17 100644 --- a/CMake/fletch-tarballs.cmake +++ b/CMake/fletch-tarballs.cmake @@ -429,9 +429,9 @@ endif() list(APPEND fletch_external_sources VTK) # VXL -set(VXL_version "0bb0ca92867408caec298cef05412ed85c6d56b7") -set(VXL_url "https://github.com/vxl/vxl/archive/${VXL_version}.zip") -set(VXL_md5 "287536149942081666a2f9a3be87a666") +set(VXL_version "2.0.2") +set(VXL_url "https://github.com/vxl/vxl/archive/v${VXL_version}.zip") +set(VXL_md5 "a32c1d69db6b1de605e010bd14cb6524") set(VXL_dlname "vxl-${VXL_version}.zip") list(APPEND fletch_external_sources VXL) From 72b34f6d1a1d82ca8d6d8252418cae6f3669d1d3 Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Fri, 28 Dec 2018 14:55:55 -0500 Subject: [PATCH 04/22] Enable modules --- CMake/External_ITK.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMake/External_ITK.cmake b/CMake/External_ITK.cmake index 17d7a5a8..f992c91e 100644 --- a/CMake/External_ITK.cmake +++ b/CMake/External_ITK.cmake @@ -68,6 +68,8 @@ ExternalProject_Add(ITK ${COMMON_CMAKE_ARGS} ${ITK_IMG_ARGS} ${itk_cmake_args} + -DModule_PhaseSymmetry:BOOL=ON + -DModule_AnisotropicDiffusionLBR:BOOL=ON ) fletch_external_project_force_install(PACKAGE ITK) From d265038d2b002e2f0a2bd90b314208767de51bd8 Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Fri, 28 Dec 2018 17:33:28 -0500 Subject: [PATCH 05/22] Adjust flags for latest VXL changes Conflicts: CMake/External_VXL.cmake --- CMake/External_VXL.cmake | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/CMake/External_VXL.cmake b/CMake/External_VXL.cmake index cf31b442..18ea93a1 100644 --- a/CMake/External_VXL.cmake +++ b/CMake/External_VXL.cmake @@ -47,16 +47,16 @@ add_package_dependency( ) set(VXL_ARGS_CONTRIB - -DBUILD_CONTRIB:BOOL=ON - -DBUILD_RPL:BOOL=ON - -DBUILD_BRL:BOOL=OFF - -DBUILD_MUL_TOOLS:BOOL=OFF - -DBUILD_PRIP:BOOL=OFF + -DVXL_BUILD_CONTRIB:BOOL=ON + -DVXL_BUILD_RPL:BOOL=ON + -DVXL_BUILD_BRL:BOOL=OFF + -DVXL_BUILD_MUL_TOOLS:BOOL=OFF + -DVXL_BUILD_PRIP:BOOL=OFF ) # Handle FFMPEG disable flag list(APPEND VXL_ARGS_VIDL - -DBUILD_CORE_VIDEO:BOOL=ON + -DVXL_BUILD_CORE_VIDEO:BOOL=ON ) if(fletch_ENABLE_FFmpeg) add_package_dependency( @@ -105,20 +105,20 @@ ExternalProject_Add(VXL ${VXL_ARGS_V3P} ${VXL_EXTRA_CMAKE_CXX_FLAGS} ${COMMON_CMAKE_ARGS} - -DBUILD_EXAMPLES:BOOL=OFF -DBUILD_TESTING:BOOL=OFF - -DBUILD_DOCUMENTATION:BOOL=OFF - -DBUILD_FOR_VXL_DASHBOARD:BOOL=ON - -DBUILD_CORE_PROBABILITY:BOOL=ON - -DBUILD_CORE_GEOMETRY:BOOL=ON - -DBUILD_CORE_NUMERICS:BOOL=ON - -DBUILD_CORE_IMAGING:BOOL=ON - -DBUILD_CORE_SERIALISATION:BOOL=ON - -DBUILD_BRL:BOOL=OFF - -DBUILD_GEL:BOOL=OFF - -DBUILD_MUL:BOOL=OFF - -DBUILD_MUL_TOOLS:BOOL=OFF - -DBUILD_TBL:BOOL=OFF + -DVXL_BUILD_EXAMPLES:BOOL=OFF + -DVXL_BUILD_DOCUMENTATION:BOOL=OFF + -DVXL_BUILD_FOR_VXL_DASHBOARD:BOOL=ON + -DVXL_BUILD_CORE_PROBABILITY:BOOL=ON + -DVXL_BUILD_CORE_GEOMETRY:BOOL=ON + -DVXL_BUILD_CORE_NUMERICS:BOOL=ON + -DVXL_BUILD_CORE_IMAGING:BOOL=ON + -DVXL_BUILD_CORE_SERIALISATION:BOOL=ON + -DVXL_BUILD_BRL:BOOL=OFF + -DVXL_BUILD_GEL:BOOL=OFF + -DVXL_BUILD_MUL:BOOL=OFF + -DVXL_BUILD_MUL_TOOLS:BOOL=OFF + -DVXL_BUILD_TBL:BOOL=OFF -DVXL_USE_DCMTK:BOOL=OFF -DJPEG_LIBRARY:FILEPATH=${JPEG_LIBRARY} -DJPEG_INCLUDE_DIR:PATH=${JPEG_INCLUDE_DIR} From 13fc389bdb3fb408999c335aa123c6f99049b693 Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Fri, 28 Dec 2018 18:30:55 -0500 Subject: [PATCH 06/22] Patch ffmpeg issue Conflicts: CMake/External_VXL.cmake --- CMake/External_VXL.cmake | 4 ++ Patches/VXL/FindFFMPEG.cmake | 91 ++++++++++++++++++++++++++++++++++++ Patches/VXL/Patch.cmake | 10 ++++ 3 files changed, 105 insertions(+) create mode 100644 Patches/VXL/FindFFMPEG.cmake create mode 100644 Patches/VXL/Patch.cmake diff --git a/CMake/External_VXL.cmake b/CMake/External_VXL.cmake index 18ea93a1..060cac55 100644 --- a/CMake/External_VXL.cmake +++ b/CMake/External_VXL.cmake @@ -97,6 +97,10 @@ ExternalProject_Add(VXL DOWNLOAD_NAME ${VXL_dlname} ${COMMON_EP_ARGS} ${COMMON_CMAKE_EP_ARGS} + PATCH_COMMAND ${CMAKE_COMMAND} + -DVXL_patch:PATH=${fletch_SOURCE_DIR}/Patches/VXL + -DVXL_source:PATH=${fletch_BUILD_PREFIX}/src/VXL + -P ${fletch_SOURCE_DIR}/Patches/VXL/Patch.cmake CMAKE_ARGS ${KWIVER_ARGS_COMMON} ${VXL_ARGS_GUI} diff --git a/Patches/VXL/FindFFMPEG.cmake b/Patches/VXL/FindFFMPEG.cmake new file mode 100644 index 00000000..f3569e61 --- /dev/null +++ b/Patches/VXL/FindFFMPEG.cmake @@ -0,0 +1,91 @@ +# Find the FFmpeg library +# +# Sets +# FFMPEG_FOUND. If false, don't try to use ffmpeg +# FFMPEG_FOUND_SEVERAL. If true, there are several directories with headers (not only ../ffmpeg/) +# FFMPEG_INCLUDE_DIR +# FFMPEG_LIBRARIES + +set( FFMPEG_FOUND "NO" ) + +find_path( FFMPEG_INCLUDE1_DIR ffmpeg/avcodec.h + /usr/include + /usr/local/include +) +find_path( FFMPEG_INCLUDE2_DIR libavcodec/avcodec.h + /usr/include + /usr/local/include +) +if( FFMPEG_INCLUDE1_DIR ) + set( FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE1_DIR} ) +endif() + +if( FFMPEG_INCLUDE2_DIR ) + set( FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE2_DIR} ) +endif() + +if( FFMPEG_INCLUDE_DIR AND FFMPEG_INCLUDE2_DIR ) + set( FFMPEG_FOUND_SEVERAL "YES" ) +else() + set( FFMPEG_FOUND_SEVERAL "NO" ) +endif() + +find_program( FFMPEG_CONFIG ffmpeg-config + /usr/bin + /usr/local/bin + ${HOME}/bin +) + +if( FFMPEG_CONFIG ) + exec_program( ${FFMPEG_CONFIG} ARGS "--libs avformat" OUTPUT_VARIABLE FFMPEG_LIBS ) + set( FFMPEG_FOUND "YES" ) + set( FFMPEG_LIBRARIES "${FFMPEG_LIBS}" ) + +else() + + find_library( FFMPEG_avcodec_LIBRARY avcodec + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + find_library( FFMPEG_avformat_LIBRARY avformat + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + find_library( FFMPEG_avutil_LIBRARY avutil + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + find_library( FFMPEG_swscale_LIBRARY swscale + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + if( FFMPEG_avcodec_LIBRARY ) + if( FFMPEG_avformat_LIBRARY ) + + set( FFMPEG_FOUND "YES" ) + set( FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} ${FFMPEG_avcodec_LIBRARY} ) + if( FFMPEG_avutil_LIBRARY ) + set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_avutil_LIBRARY} ) + endif() + if( FFMPEG_swscale_LIBRARY ) + set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_swscale_LIBRARY} ) + endif() + + endif() + endif() + +endif() + +endif() diff --git a/Patches/VXL/Patch.cmake b/Patches/VXL/Patch.cmake new file mode 100644 index 00000000..1a4005a5 --- /dev/null +++ b/Patches/VXL/Patch.cmake @@ -0,0 +1,10 @@ +#+ +# This file is called as CMake -P script for the patch step of +# External_VXL.cmake to fix a minor ffmpeg find flag +#- + +message("Patching VXL in ${VXL_source}") + +file(COPY ${VXL_patch}/FindFFMPEG.cmake + DESTINATION ${VXL_source}/config/cmake/Modules/NewCMake/ +) From 14007ca5b1509b6c597284f7bed6c4271c207d31 Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Fri, 28 Dec 2018 18:49:24 -0500 Subject: [PATCH 07/22] Cleanup patch --- Patches/VXL/FindFFMPEG.cmake | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/Patches/VXL/FindFFMPEG.cmake b/Patches/VXL/FindFFMPEG.cmake index f3569e61..c6c8eb7e 100644 --- a/Patches/VXL/FindFFMPEG.cmake +++ b/Patches/VXL/FindFFMPEG.cmake @@ -72,20 +72,16 @@ else() ) if( FFMPEG_avcodec_LIBRARY ) - if( FFMPEG_avformat_LIBRARY ) - - set( FFMPEG_FOUND "YES" ) - set( FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} ${FFMPEG_avcodec_LIBRARY} ) - if( FFMPEG_avutil_LIBRARY ) - set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_avutil_LIBRARY} ) - endif() - if( FFMPEG_swscale_LIBRARY ) - set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_swscale_LIBRARY} ) + if( FFMPEG_avformat_LIBRARY ) + set( FFMPEG_FOUND "YES" ) + set( FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} ${FFMPEG_avcodec_LIBRARY} ) + if( FFMPEG_avutil_LIBRARY ) + set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_avutil_LIBRARY} ) + endif() + if( FFMPEG_swscale_LIBRARY ) + set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_swscale_LIBRARY} ) + endif() endif() - endif() - endif() - -endif() endif() From 814e90a840fac266f0b493c4e2e9c74a8e0bfbd2 Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Fri, 28 Dec 2018 19:09:48 -0500 Subject: [PATCH 08/22] Modify patch Conflicts: Patches/VXL/FindFFMPEG.cmake --- Patches/VXL/FindFFMPEG.cmake | 87 ---- Patches/VXL/Patch.cmake | 4 +- Patches/VXL/vidl_ffmpeg_ostream_v56.hxx | 606 ++++++++++++++++++++++++ 3 files changed, 608 insertions(+), 89 deletions(-) delete mode 100644 Patches/VXL/FindFFMPEG.cmake create mode 100644 Patches/VXL/vidl_ffmpeg_ostream_v56.hxx diff --git a/Patches/VXL/FindFFMPEG.cmake b/Patches/VXL/FindFFMPEG.cmake deleted file mode 100644 index c6c8eb7e..00000000 --- a/Patches/VXL/FindFFMPEG.cmake +++ /dev/null @@ -1,87 +0,0 @@ -# Find the FFmpeg library -# -# Sets -# FFMPEG_FOUND. If false, don't try to use ffmpeg -# FFMPEG_FOUND_SEVERAL. If true, there are several directories with headers (not only ../ffmpeg/) -# FFMPEG_INCLUDE_DIR -# FFMPEG_LIBRARIES - -set( FFMPEG_FOUND "NO" ) - -find_path( FFMPEG_INCLUDE1_DIR ffmpeg/avcodec.h - /usr/include - /usr/local/include -) -find_path( FFMPEG_INCLUDE2_DIR libavcodec/avcodec.h - /usr/include - /usr/local/include -) -if( FFMPEG_INCLUDE1_DIR ) - set( FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE1_DIR} ) -endif() - -if( FFMPEG_INCLUDE2_DIR ) - set( FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE2_DIR} ) -endif() - -if( FFMPEG_INCLUDE_DIR AND FFMPEG_INCLUDE2_DIR ) - set( FFMPEG_FOUND_SEVERAL "YES" ) -else() - set( FFMPEG_FOUND_SEVERAL "NO" ) -endif() - -find_program( FFMPEG_CONFIG ffmpeg-config - /usr/bin - /usr/local/bin - ${HOME}/bin -) - -if( FFMPEG_CONFIG ) - exec_program( ${FFMPEG_CONFIG} ARGS "--libs avformat" OUTPUT_VARIABLE FFMPEG_LIBS ) - set( FFMPEG_FOUND "YES" ) - set( FFMPEG_LIBRARIES "${FFMPEG_LIBS}" ) - -else() - - find_library( FFMPEG_avcodec_LIBRARY avcodec - /usr/lib - /usr/local/lib - /usr/lib64 - /usr/local/lib64 - ) - - find_library( FFMPEG_avformat_LIBRARY avformat - /usr/lib - /usr/local/lib - /usr/lib64 - /usr/local/lib64 - ) - - find_library( FFMPEG_avutil_LIBRARY avutil - /usr/lib - /usr/local/lib - /usr/lib64 - /usr/local/lib64 - ) - - find_library( FFMPEG_swscale_LIBRARY swscale - /usr/lib - /usr/local/lib - /usr/lib64 - /usr/local/lib64 - ) - - if( FFMPEG_avcodec_LIBRARY ) - if( FFMPEG_avformat_LIBRARY ) - set( FFMPEG_FOUND "YES" ) - set( FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} ${FFMPEG_avcodec_LIBRARY} ) - if( FFMPEG_avutil_LIBRARY ) - set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_avutil_LIBRARY} ) - endif() - if( FFMPEG_swscale_LIBRARY ) - set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_swscale_LIBRARY} ) - endif() - endif() - endif() - -endif() diff --git a/Patches/VXL/Patch.cmake b/Patches/VXL/Patch.cmake index 1a4005a5..1e4b7c8e 100644 --- a/Patches/VXL/Patch.cmake +++ b/Patches/VXL/Patch.cmake @@ -5,6 +5,6 @@ message("Patching VXL in ${VXL_source}") -file(COPY ${VXL_patch}/FindFFMPEG.cmake - DESTINATION ${VXL_source}/config/cmake/Modules/NewCMake/ +file(COPY ${VXL_patch}//vidl_ffmpeg_ostream_v56.hxx + DESTINATION ${VXL_source}/core/vidl/ ) diff --git a/Patches/VXL/vidl_ffmpeg_ostream_v56.hxx b/Patches/VXL/vidl_ffmpeg_ostream_v56.hxx new file mode 100644 index 00000000..1e4d4686 --- /dev/null +++ b/Patches/VXL/vidl_ffmpeg_ostream_v56.hxx @@ -0,0 +1,606 @@ +// This is core/vidl/vidl_ffmpeg_ostream_v56.hxx +#ifndef vidl_ffmpeg_ostream_v56_hxx_ +#define vidl_ffmpeg_ostream_v56_hxx_ +#pragma once + +#include +#include +#include "vidl_ffmpeg_ostream.h" +//: +// \file +// \author Johan Andruejol +// \author Gehua Yang +// \author Matt Leotta +// \author Amitha Perera +// \author David Law +// \date 6 April 2015 +// +// Update implementation based on FFMPEG release version 2.8.4 +// +//----------------------------------------------------------------------------- + +#include "vidl_ffmpeg_init.h" +#include "vidl_ffmpeg_convert.h" +#include "vidl_ffmpeg_pixel_format.h" +#include "vidl_frame.h" +#include "vidl_convert.h" +#ifdef _MSC_VER +# include +#endif +#include +#include + +extern "C" { +#if FFMPEG_IN_SEVERAL_DIRECTORIES +#include +#include +#include +#include + +#else +#include +#include +#endif +} + +//----------------------------------------------------------------------------- + + +struct vidl_ffmpeg_ostream::pimpl +{ + pimpl() + : fmt_cxt_( nullptr ), + file_opened_( false ), + codec_opened_( false ), + cur_frame_( 0 ), + video_rc_eq_( nullptr ) + { } + + AVFormatContext* fmt_cxt_; + bool file_opened_; + bool codec_opened_; + unsigned int cur_frame_; + char* video_rc_eq_; +}; + + +//----------------------------------------------------------------------------- + + +//: Constructor +vidl_ffmpeg_ostream:: +vidl_ffmpeg_ostream() + : os_( new vidl_ffmpeg_ostream::pimpl ) +{ + vidl_ffmpeg_init(); +} + + +//: Destructor +vidl_ffmpeg_ostream:: +~vidl_ffmpeg_ostream() +{ + close(); + delete os_; +} + + +//: Constructor - opens a stream +vidl_ffmpeg_ostream:: +vidl_ffmpeg_ostream(const std::string & filename, + const vidl_ffmpeg_ostream_params & params) + : os_( new vidl_ffmpeg_ostream::pimpl ), + filename_(std::move(filename)), params_(std::move(params)) +{ + vidl_ffmpeg_init(); +} + + +//: Open the stream +bool +vidl_ffmpeg_ostream:: +open() +{ + // Close any open files + close(); + + os_->fmt_cxt_ = avformat_alloc_context(); + + AVOutputFormat* file_oformat = nullptr; + if ( params_.file_format_ == vidl_ffmpeg_ostream_params::GUESS ) { + file_oformat = av_guess_format(nullptr, filename_.c_str(), nullptr); + if (!file_oformat) { + std::cerr << "ffmpeg: Unable for find a suitable output format for " + << filename_ << '\n'; + close(); + return false; + } + } + else { + close(); + return false; + } + + os_->fmt_cxt_->oformat = file_oformat; + os_->fmt_cxt_->nb_streams = 0; + + // Create stream + AVStream* st = avformat_new_stream( os_->fmt_cxt_, nullptr ); + if ( !st ) { + std::cerr << "ffmpeg: could not alloc stream\n"; + close(); + return false; + } + + //os_->fmt_cxt_->nb_streams = 1; + + AVCodecContext *video_enc = st->codec; + + if (std::strcmp(file_oformat->name, "mp4") != 0 || + std::strcmp(file_oformat->name, "mov") != 0 || + std::strcmp(file_oformat->name, "3gp") != 0 ) + video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER; + + video_enc->codec_type = AVMEDIA_TYPE_VIDEO; + + switch ( params_.encoder_ ) + { + case vidl_ffmpeg_ostream_params::DEFAULT: + video_enc->codec_id = file_oformat->video_codec; + break; + case vidl_ffmpeg_ostream_params::MPEG4: + video_enc->codec_id = AV_CODEC_ID_MPEG4; + break; + case vidl_ffmpeg_ostream_params::MPEG2VIDEO: + video_enc->codec_id = AV_CODEC_ID_MPEG2VIDEO; + break; + case vidl_ffmpeg_ostream_params::MSMPEG4V2: + video_enc->codec_id = AV_CODEC_ID_MSMPEG4V2; + break; + case vidl_ffmpeg_ostream_params::RAWVIDEO: + video_enc->codec_id = AV_CODEC_ID_RAWVIDEO; + break; + case vidl_ffmpeg_ostream_params::LJPEG: + video_enc->codec_id = AV_CODEC_ID_LJPEG; + break; + case vidl_ffmpeg_ostream_params::HUFFYUV: + video_enc->codec_id = AV_CODEC_ID_HUFFYUV; + break; + case vidl_ffmpeg_ostream_params::DVVIDEO: + video_enc->codec_id = AV_CODEC_ID_DVVIDEO; + break; + default: + std::cout << "ffmpeg: Unknown encoder type\n"; + return false; + } + + AVCodec* codec = avcodec_find_encoder( video_enc->codec_id ); + if ( !codec ) + { + std::cerr << "ffmpeg_writer:: couldn't find encoder for " << video_enc->codec_id << '\n'; + return false; + } + + video_enc->bit_rate = params_.bit_rate_ * 1000; + video_enc->bit_rate_tolerance = params_.video_bit_rate_tolerance_; + video_enc->time_base.num = 1000; + video_enc->time_base.den = int(params_.frame_rate_*1000); + + if ( codec && codec->supported_framerates ) + { + AVRational const* p = codec->supported_framerates; + AVRational req = { video_enc->time_base.den, video_enc->time_base.num }; + AVRational const* best = nullptr; + AVRational best_error = { INT_MAX, 1 }; + for (; p->den!=0; p++) + { + AVRational error = av_sub_q(req, *p); + if ( error.num < 0 ) error.num *= -1; + if ( av_cmp_q( error, best_error ) < 0 ) + { + best_error= error; + best= p; + } + } + video_enc->time_base.den= best->num; + video_enc->time_base.num= best->den; + } + + video_enc->width = params_.ni_; + video_enc->height = params_.nj_; + video_enc->sample_aspect_ratio = av_d2q(params_.frame_aspect_ratio_*params_.ni_/params_.nj_, 255); + + // Our source is packed RGB. Use that if possible. + video_enc->pix_fmt = AV_PIX_FMT_RGB24; + if ( codec && codec->pix_fmts ) + { + const enum AVPixelFormat* p= codec->pix_fmts; + for ( ; *p != -1; p++ ) + { + if ( *p == video_enc->pix_fmt ) + break; + } + if ( *p == -1 ) + video_enc->pix_fmt = codec->pix_fmts[0]; + } + else if ( codec && ( codec->id == AV_CODEC_ID_RAWVIDEO || + codec->id == AV_CODEC_ID_HUFFYUV ) ) + { + // these formats only support the YUV input image formats + video_enc->pix_fmt = AV_PIX_FMT_YUV420P; + } + + if (!params_.intra_only_) + video_enc->gop_size = params_.gop_size_; + else + video_enc->gop_size = 0; + if (params_.video_qscale_ || params_.same_quality_) + { + video_enc->flags |= CODEC_FLAG_QSCALE; + video_enc->global_quality = FF_QP2LAMBDA * params_.video_qscale_; + } + // if (bitexact) + // video_enc->flags |= CODEC_FLAG_BITEXACT; + + video_enc->mb_decision = params_.mb_decision_; + video_enc->mb_cmp = params_.mb_cmp_; + video_enc->ildct_cmp = params_.ildct_cmp_; + video_enc->me_sub_cmp = params_.sub_cmp_; + video_enc->me_cmp = params_.cmp_; + video_enc->me_pre_cmp = params_.pre_cmp_; + video_enc->pre_me = params_.pre_me_; + video_enc->lumi_masking = params_.lumi_mask_; + video_enc->dark_masking = params_.dark_mask_; + video_enc->spatial_cplx_masking = params_.scplx_mask_; + video_enc->temporal_cplx_masking = params_.tcplx_mask_; + video_enc->p_masking = params_.p_mask_; + // This parameter is no longer supported + //video_enc->quantizer_noise_shaping= params_.qns_; + + if (params_.use_umv_) + { + // This flag is no longer supported + std::cerr << "WARNING: global parameter 'use_umv_' no longer support by FFMPEG" << std::endl; + //video_enc->flags |= CODEC_FLAG_H263P_UMV; + } + if (params_.use_ss_) + { + // This flag is no longer supported + std::cerr << "WARNING: global parameter 'use_ss_' no longer support by FFMPEG" << std::endl; + //video_enc->flags |= CODEC_FLAG_H263P_SLICE_STRUCT; + } + if (params_.use_aiv_) + { + // This flag is no longer supported + std::cerr << "WARNING: global parameter 'use_aiv_' no longer support by FFMPEG" << std::endl; + //video_enc->flags |= CODEC_FLAG_H263P_AIV; + } + if (params_.use_4mv_) + { + video_enc->flags |= CODEC_FLAG_4MV; + } + if (params_.use_obmc_) + { + // This flag is no longer supported + std::cerr << "WARNING: global parameter 'use_obmc_' no longer support by FFMPEG" << std::endl; + //video_enc->flags |= CODEC_FLAG_OBMC; + } + if (params_.use_loop_) + { + video_enc->flags |= CODEC_FLAG_LOOP_FILTER; + } + + if (params_.use_part_) + { + // This flag is no longer supported + std::cerr << "WARNING: global parameter 'use_part_' no longer support by FFMPEG" << std::endl; + //video_enc->flags |= CODEC_FLAG_PART; + } + if (params_.use_alt_scan_) + { + // This flag is no longer supported + std::cerr << "WARNING: global parameter 'use_alt_scan_' no longer support by FFMPEG" << std::endl; + //video_enc->flags |= CODEC_FLAG_ALT_SCAN; + } + if (params_.use_scan_offset_) + { + // This flag is no longer supported + std::cerr << "WARNING: global parameter 'use_scan_offset_' no longer support by FFMPEG" << std::endl; + //video_enc->flags |= CODEC_FLAG_SVCD_SCAN_OFFSET; + } + if (params_.closed_gop_) + { + video_enc->flags |= CODEC_FLAG_CLOSED_GOP; + } + if (params_.use_qpel_) + { + video_enc->flags |= CODEC_FLAG_QPEL; + } + //if (params_.use_qprd_) + //{ + // video_enc->flags |= CODEC_FLAG_QP_RD; + //} + //if (params_.use_cbprd_) + //{ + // video_enc->flags |= CODEC_FLAG_CBP_RD; + //} + if (params_.b_frames_) + { + video_enc->max_b_frames = params_.b_frames_; + video_enc->b_frame_strategy = 0; + video_enc->b_quant_factor = 2.0; + } + if (params_.do_interlace_dct_) + { + video_enc->flags |= CODEC_FLAG_INTERLACED_DCT; + } + if (params_.do_interlace_me_) + { + video_enc->flags |= CODEC_FLAG_INTERLACED_ME; + } + video_enc->qmin = params_.video_qmin_; + video_enc->qmax = params_.video_qmax_; + av_opt_set_int(video_enc, "lmin", params_.video_lmin_, AV_OPT_SEARCH_CHILDREN); + av_opt_set_int(video_enc, "lmax", params_.video_lmax_, AV_OPT_SEARCH_CHILDREN); + video_enc->max_qdiff = params_.video_qdiff_; + video_enc->qblur = params_.video_qblur_; + video_enc->qcompress = params_.video_qcomp_; + + // delete when the stream is closed + os_->video_rc_eq_ = new char[params_.video_rc_eq_.length() + 1]; + av_opt_set(video_enc, "video_rc_eq_", params_.video_rc_eq_.c_str(), AV_OPT_SEARCH_CHILDREN); + + video_enc->debug = params_.debug_; + video_enc->debug_mv = params_.debug_mv_; + video_enc->thread_count = 1; + + video_enc->rc_max_rate = params_.video_rc_max_rate_; + video_enc->rc_min_rate = params_.video_rc_min_rate_; + av_opt_set_double(video_enc, "rc_buffer_aggressivity", params_.video_rc_buffer_aggressivity_, AV_OPT_SEARCH_CHILDREN); + av_opt_set_double(video_enc, "rc_initial_cplx", params_.video_rc_initial_cplx_, AV_OPT_SEARCH_CHILDREN); + video_enc->i_quant_factor = params_.video_i_qfactor_; + video_enc->b_quant_factor = params_.video_b_qfactor_; + video_enc->i_quant_offset = params_.video_i_qoffset_; + video_enc->b_quant_offset = params_.video_b_qoffset_; + //DEPRECATED https://www.ffmpeg.org/doxygen/3.1/structAVCodecContext.html video_enc->intra_quant_bias = params_.video_intra_quant_bias_; + //DEPRECATED https://www.ffmpeg.org/doxygen/3.1/structAVCodecContext.html video_enc->inter_quant_bias = params_.video_inter_quant_bias_; + video_enc->dct_algo = params_.dct_algo_; + video_enc->idct_algo = params_.idct_algo_; + video_enc->intra_dc_precision = params_.intra_dc_precision_ - 8; + video_enc->strict_std_compliance = params_.strict_; + av_opt_set_double(video_enc, "error_rate", params_.error_rate_, AV_OPT_SEARCH_CHILDREN); + video_enc->noise_reduction = params_.noise_reduction_; + video_enc->scenechange_threshold = params_.sc_threshold_; + video_enc->me_range = params_.me_range_; + video_enc->coder_type = params_.coder_; + video_enc->context_model = params_.context_; + video_enc->prediction_method = params_.predictor_; + + if (params_.do_psnr_) + video_enc->flags|= CODEC_FLAG_PSNR; + + //DEPRECATED: This option does nothing "https://www.ffmpeg.org/doxygen/3.1/structAVCodecContext.html#aa71b3450f1a508330e907db117ae410e" video_enc->me_method = params_.me_method_; + + // two pass mode + if (params_.do_pass_) + { + if (params_.do_pass_ == 1) + { + video_enc->flags |= CODEC_FLAG_PASS1; + } + else + { + video_enc->flags |= CODEC_FLAG_PASS2; + } + } + + std::strncpy( os_->fmt_cxt_->filename, filename_.c_str(), 1023 ); + + if ( avio_open( &os_->fmt_cxt_->pb, filename_.c_str(), AVIO_FLAG_WRITE ) < 0 ) + { + std::cerr << "ffmpeg: couldn't open " << filename_ << " for writing\n"; + close(); + return false; + } + os_->file_opened_ = true; + + //dump_format( os_->fmt_cxt_, 1, filename_, 1 ); + + if ( avcodec_open2( video_enc, codec, nullptr ) < 0 ) + { + std::cerr << "ffmpeg: couldn't open codec\n"; + close(); + return false; + } + os_->codec_opened_ = true; + + if ( avformat_write_header( os_->fmt_cxt_, nullptr ) < 0 ) + { + std::cerr << "ffmpeg: couldn't write header\n"; + close(); + return false; + } + + return true; +} + + +//: Close the stream +void +vidl_ffmpeg_ostream:: +close() +{ + //delete os_->video_rc_eq_; + //os_->video_rc_eq_ = NULL; + + if ( os_->fmt_cxt_ ) { + + // flush out remaining packets refer to + // http://stackoverflow.com/questions/17816532/creating-a-video-from-images-using-ffmpeg-libav-and-libx264 + AVCodecContext* codec = os_->fmt_cxt_->streams[0]->codec; + int got_packet = 1; + while (got_packet) + { + AVPacket pkt; + av_init_packet(&pkt); + pkt.data = nullptr; + pkt.size = 0; + pkt.stream_index = 0; + + int ret = avcodec_encode_video2(codec, &pkt, nullptr, &got_packet); + + if (ret < 0) + { + std::cerr << "FFMPEG video encoding failed" << std::endl; + break; + } + if (got_packet) { + if (codec->coded_frame) { + pkt.pts = codec->coded_frame->pts; + } + if (codec->coded_frame && codec->coded_frame->key_frame) { + pkt.flags |= AV_PKT_FLAG_KEY; + } + av_interleaved_write_frame(os_->fmt_cxt_, &pkt); + av_packet_unref(&pkt); + + } + } + + if ( os_->file_opened_ ) { + av_write_trailer( os_->fmt_cxt_ ); + avio_close( os_->fmt_cxt_->pb ); + os_->file_opened_ = false; + } + + if ( os_->fmt_cxt_->nb_streams > 0 ) { + if ( os_->codec_opened_ ) { + for ( unsigned i = 0; i < os_->fmt_cxt_->nb_streams; ++i ) { + AVCodecContext* codec = os_->fmt_cxt_->streams[i]->codec; + if ( codec->stats_in ) { + av_freep( codec->stats_in ); + } + avcodec_close( codec ); + } + } + os_->codec_opened_ = false; + for ( unsigned i = 0; i < os_->fmt_cxt_->nb_streams; ++i ) { + av_free( os_->fmt_cxt_->streams[i] ); + } + } + + av_free( os_->fmt_cxt_ ); + os_->fmt_cxt_ = nullptr; + } +} + + +//: Return true if the stream is open for writing +bool +vidl_ffmpeg_ostream:: +is_open() const +{ + return os_->file_opened_; +} + + +//: Write and image to the stream +// \retval false if the image could not be written +bool +vidl_ffmpeg_ostream:: +write_frame(const vidl_frame_sptr& frame) +{ + if (!is_open()) { + // resize to the first frame + params_.size(frame->ni(),frame->nj()); + open(); + } + + AVCodecContext* codec = os_->fmt_cxt_->streams[0]->codec; + + if (unsigned( codec->width ) != frame->ni() || + unsigned( codec->height) != frame->nj() ) { + std::cerr << "ffmpeg: Input image has wrong size. Expecting (" + << codec->width << 'x' << codec->height << "), got (" + << frame->ni() << 'x' << frame->nj() << ")\n"; + return false; + } + + AVPixelFormat fmt = vidl_pixel_format_to_ffmpeg(frame->pixel_format()); + + vidl_pixel_format target_fmt = vidl_pixel_format_from_ffmpeg(codec->pix_fmt); + static vidl_frame_sptr temp_frame = new vidl_shared_frame(nullptr,frame->ni(),frame->nj(),target_fmt); + + AVFrame* out_frame = av_frame_alloc(); + //avcodec_get_frame_defaults( &out_frame ); + + // The frame is in the correct format to encode directly + if ( codec->pix_fmt == fmt ) + { + avpicture_fill((AVPicture*)out_frame, (uint8_t*) frame->data(), + fmt, frame->ni(), frame->nj()); + //int ret = av_image_fill_arrays(out_frame->data, out_frame->linesize, (uint8_t*)frame->data(), + // fmt, frame->ni(), frame->nj(), 1); + } + else + { + if (!temp_frame->data()) { + unsigned ni = frame->ni(); + unsigned nj = frame->nj(); + unsigned out_size = vidl_pixel_format_buffer_size(ni,nj,target_fmt); + temp_frame = new vidl_memory_chunk_frame(ni, nj, target_fmt, + new vil_memory_chunk(out_size, VIL_PIXEL_FORMAT_BYTE)); + } + // try conversion with FFMPEG functions + if (!vidl_ffmpeg_convert(frame, temp_frame)) { + // try conversion with vidl functions + if (!vidl_convert_frame(*frame, *temp_frame)) { + std::cout << "unable to convert " << frame->pixel_format() << " to "<data(), + codec->pix_fmt, frame->ni(), frame->nj()); + //int ret = av_image_fill_arrays(out_frame->data, out_frame->linesize, (uint8_t*)temp_frame->data(), + // fmt, temp_frame->ni(), temp_frame->nj(), 1); + //ret = 0; + } + + AVPacket pkt; + av_init_packet( &pkt ); + pkt.data = nullptr; + pkt.size = 0; + pkt.stream_index = 0; + + out_frame->pts = os_->cur_frame_; + out_frame->width = codec->width; + out_frame->height = codec->height; + out_frame->format = codec->pix_fmt; + + int got_packet; + int ret = avcodec_encode_video2( codec, &pkt, out_frame, &got_packet ); + + if ( ret < 0 ) + { + std::cerr << "FFMPEG video encoding failed" <coded_frame ) { + pkt.pts = codec->coded_frame->pts; + } + if ( codec->coded_frame && codec->coded_frame->key_frame ) { + pkt.flags |= AV_PKT_FLAG_KEY; + } + av_interleaved_write_frame( os_->fmt_cxt_, &pkt ); + av_packet_unref(&pkt); + } + + ++os_->cur_frame_; + return true; +} + +#endif // vidl_ffmpeg_ostream_v56_hxx_ From 3fd0d00d609f357d5f175f73f1156bf07af2d37f Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Thu, 7 Feb 2019 20:59:16 -0500 Subject: [PATCH 09/22] Update hash --- CMake/fletch-tarballs.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMake/fletch-tarballs.cmake b/CMake/fletch-tarballs.cmake index 60895e17..8308a998 100644 --- a/CMake/fletch-tarballs.cmake +++ b/CMake/fletch-tarballs.cmake @@ -429,9 +429,9 @@ endif() list(APPEND fletch_external_sources VTK) # VXL -set(VXL_version "2.0.2") -set(VXL_url "https://github.com/vxl/vxl/archive/v${VXL_version}.zip") -set(VXL_md5 "a32c1d69db6b1de605e010bd14cb6524") +set(VXL_version "c3fd27959f51e0469a7a6075e975f245ac306f3d") +set(VXL_url "https://github.com/vxl/vxl/archive/${VXL_version}.zip") +set(VXL_md5 "9ae63bb158ae3e5e2104152093a4c46c") set(VXL_dlname "vxl-${VXL_version}.zip") list(APPEND fletch_external_sources VXL) From f1806c1f95b72a4e0edea5abc00b19ef70a5d9eb Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Sun, 10 Feb 2019 19:21:52 -0600 Subject: [PATCH 10/22] Disable OXL --- CMake/External_VXL.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/CMake/External_VXL.cmake b/CMake/External_VXL.cmake index 060cac55..3c208a1f 100644 --- a/CMake/External_VXL.cmake +++ b/CMake/External_VXL.cmake @@ -123,6 +123,7 @@ ExternalProject_Add(VXL -DVXL_BUILD_MUL:BOOL=OFF -DVXL_BUILD_MUL_TOOLS:BOOL=OFF -DVXL_BUILD_TBL:BOOL=OFF + -DVXL_BUILD_OXL:BOOL=OFF -DVXL_USE_DCMTK:BOOL=OFF -DJPEG_LIBRARY:FILEPATH=${JPEG_LIBRARY} -DJPEG_INCLUDE_DIR:PATH=${JPEG_INCLUDE_DIR} From 7bbea9b53a4dc2e5d353dc493a045915f1e99690 Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Wed, 27 Feb 2019 01:00:30 -0500 Subject: [PATCH 11/22] Add link to opencv if enabled --- CMake/External_ITK.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMake/External_ITK.cmake b/CMake/External_ITK.cmake index f992c91e..30b96872 100644 --- a/CMake/External_ITK.cmake +++ b/CMake/External_ITK.cmake @@ -58,6 +58,14 @@ if (fletch_ENABLE_VXL) list(APPEND ITK_DEPENDS VXL) endif() +if (fletch_ENABLE_OpenCV) + list (APPEND itk_cmake_args + -DModule_ITKVideoBridgeOpenCV:BOOL=ON + -DOpenCV_DIR:PATH=${OpenCV_ROOT} + ) + list(APPEND ITK_DEPENDS VXL) +endif() + ExternalProject_Add(ITK DEPENDS ${ITK_DEPENDS} URL ${ITK_file} From 167a7115e54945493040435584e39aea5ba65c79 Mon Sep 17 00:00:00 2001 From: Taylor Cook Date: Wed, 10 Apr 2019 11:29:20 -0400 Subject: [PATCH 12/22] Fix OpenCV ITK depends --- CMake/External_ITK.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/External_ITK.cmake b/CMake/External_ITK.cmake index 30b96872..b70fbe17 100644 --- a/CMake/External_ITK.cmake +++ b/CMake/External_ITK.cmake @@ -63,7 +63,7 @@ if (fletch_ENABLE_OpenCV) -DModule_ITKVideoBridgeOpenCV:BOOL=ON -DOpenCV_DIR:PATH=${OpenCV_ROOT} ) - list(APPEND ITK_DEPENDS VXL) + list(APPEND ITK_DEPENDS OpenCV) endif() ExternalProject_Add(ITK From d5bbf06fcd8d9d34057f0623ae2f3162f1371049 Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Sun, 10 Feb 2019 19:31:02 -0600 Subject: [PATCH 13/22] Add patch for windows linking issues --- Patches/VXL/Patch.cmake | 12 + Patches/VXL/vnl_io_matrix.hxx | 99 +++ Patches/VXL/vnl_matrix_fixed.h | 1027 ++++++++++++++++++++++++++++++++ Patches/VXL/vnl_transpose.h | 77 +++ 4 files changed, 1215 insertions(+) create mode 100644 Patches/VXL/vnl_io_matrix.hxx create mode 100644 Patches/VXL/vnl_matrix_fixed.h create mode 100644 Patches/VXL/vnl_transpose.h diff --git a/Patches/VXL/Patch.cmake b/Patches/VXL/Patch.cmake index 1e4b7c8e..21ed9ada 100644 --- a/Patches/VXL/Patch.cmake +++ b/Patches/VXL/Patch.cmake @@ -8,3 +8,15 @@ message("Patching VXL in ${VXL_source}") file(COPY ${VXL_patch}//vidl_ffmpeg_ostream_v56.hxx DESTINATION ${VXL_source}/core/vidl/ ) + +file(COPY ${VXL_patch}//vnl_matrix_fixed.h + DESTINATION ${VXL_source}/core/vnl/ +) + +file(COPY ${VXL_patch}//vnl_io_matrix.h + DESTINATION ${VXL_source}/core/vnl/ +) + +file(COPY ${VXL_patch}//vnl_io_matrix.hxx + DESTINATION ${VXL_source}/core/vnl/io/ +) diff --git a/Patches/VXL/vnl_io_matrix.hxx b/Patches/VXL/vnl_io_matrix.hxx new file mode 100644 index 00000000..1ecbbd76 --- /dev/null +++ b/Patches/VXL/vnl_io_matrix.hxx @@ -0,0 +1,99 @@ +// This is core/vnl/io/vnl_io_matrix.hxx +#ifndef vnl_io_matrix_hxx_ +#define vnl_io_matrix_hxx_ +//: +// \file + +#include "vnl_io_matrix.h" +#include +#include +#include +#include + +//================================================================================= +//: Binary save self to stream. +template +void vsl_b_write(vsl_b_ostream & os, const vnl_matrix & p) +{ + constexpr short version_no = 2; + vsl_b_write(os, version_no); + vsl_b_write(os, p.rows()); + vsl_b_write(os, p.cols()); + + // Calling p.begin() on empty matrix causes segfault + if (p.size()>0) + vsl_block_binary_write(os, p.begin(), p.size()); +} + +//================================================================================= +//: Binary load self from stream. +template +void vsl_b_read(vsl_b_istream &is, vnl_matrix & p) +{ + if (!is) return; + + short v; + unsigned m, n; + vsl_b_read(is, v); + switch (v) + { + case 1: + vsl_b_read(is, m); + vsl_b_read(is, n); + p.set_size(m, n); + // Calling begin() on empty matrix causes segfault + if (m*n>0) + vsl_b_read_block_old(is, p.begin(), p.size()); + break; + + case 2: + vsl_b_read(is, m); + vsl_b_read(is, n); + p.set_size(m, n); + // Calling begin() on empty matrix causes segfault + if (m*n>0) + vsl_block_binary_read(is, p.data_block(), p.size()); + break; + + default: + std::cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, vnl_matrix&)\n" + << " Unknown version number "<< v << '\n'; + is.is().clear(std::ios::badbit); // Set an unrecoverable IO error on stream + return; + } +} + +//==================================================================================== +//: Output a human readable summary to the stream +template +void vsl_print_summary(std::ostream & os,const vnl_matrix & p) +{ + os<<"Size: "<p.rows()) m=p.rows(); + if (n>p.cols()) n=p.cols(); + + vsl_indent_inc(os); + for (unsigned int i=0;in) os<<"..."; + os<<")\n"; + } + if (p.rows()>m) os < &); \ +template void vsl_b_read(vsl_b_istream &, vnl_matrix &); \ +template void vsl_b_write(vsl_b_ostream &, const vnl_matrix &) + +#endif // vnl_io_matrix_hxx_ diff --git a/Patches/VXL/vnl_matrix_fixed.h b/Patches/VXL/vnl_matrix_fixed.h new file mode 100644 index 00000000..8008fd9b --- /dev/null +++ b/Patches/VXL/vnl_matrix_fixed.h @@ -0,0 +1,1027 @@ +// This is core/vnl/vnl_matrix_fixed.h +#ifndef vnl_matrix_fixed_h_ +#define vnl_matrix_fixed_h_ +//: +// \file +// \brief fixed size matrix +// +// \author Andrew W. Fitzgibbon, Oxford RRG +// \date 04 Aug 96 +// +// \verbatim +// Modifications +// Peter Vanroose, 23 Nov 1996: added explicit copy constructor +// LSB (Manchester) 15/03/2001: added Binary I/O and tidied up the documentation +// Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line +// Oct.2002 - Amitha Perera - separated vnl_matrix and vnl_matrix_fixed, +// removed necessity for vnl_matrix_fixed_ref +// Oct.2002 - Peter Vanroose - added inplace_transpose() method +// Jul.2003 - Paul Smyth - fixed end() bug, made op*=() more general +// Mar.2009 - Peter Vanroose - added arg_min() and arg_max() +// Oct.2010 - Peter Vanroose - mutators and filling methods now return *this +// Jan.2011 - Peter Vanroose - added methods set_diagonal() & get_diagonal() +// \endverbatim +//----------------------------------------------------------------------------- + +#include +#include +#include +#include +#ifdef _MSC_VER +# include +#endif + +#include "vnl_matrix.h" +#include "vnl_matrix_ref.h" +#include +#include // needed for e.g. vnl_matrix_fixed_mat_vec_mult() +#include +#include // for VNL_CONFIG_CHECK_BOUNDS +#include "vnl/vnl_export.h" + +template class vnl_matrix_fixed; + +// This mess is for a MSVC6 workaround. +// +// The problem: the matrix-matrix operator* should be written as a +// non-member function since vxl (currently) forbids the use of member +// templates. However, when declared as +// \code +// template +// matrix operator*( matrix, matrix ); +// \endcode +// MSVC6 does not find it. A solution is to declare it as a member +// template. However, the obvious +// \code +// template +// matrix operator*( matrix ); +// \endcode +// causes an internal compiler error. It turns out that if the new +// template parameter "o" comes _first_, then all is okay. Now, we +// can't change the signature of vnl_matrix_fixed to , so we use a "hidden" helper matrix. Except +// that user defined conversion operators and conversion constructors +// are not called for templated functions. So we have to use a helper +// base class. The base class is empty, which means that there is no +// loss in space or time efficiency. Finally, we have: +// \code +// template +// class fake_base { }; +// +// template +// class matrix : public fake_base +// { +// template +// matrix operator*( fake_base ); +// }; +// \endcode +// Notice how "o" is first in the list of template parameters. Since +// base class conversions _are_ performed during template matching, +// matrix is matched as fake_base, and all is good. For +// some values of good. +// +// Of course, all this trickery is pre-processed away for conforming +// compilers. +// +template +class vnl_matrix_fixed; +template +inline +vnl_vector_fixed vnl_matrix_fixed_mat_vec_mult(const vnl_matrix_fixed& a, const vnl_vector_fixed& b); +template +inline +vnl_matrix_fixed vnl_matrix_fixed_mat_mat_mult(const vnl_matrix_fixed& a, const vnl_matrix_fixed& b); + +//: Fixed size, stack-stored, space-efficient matrix. +// vnl_matrix_fixed is a fixed-length, stack storage vector. It has +// the same storage size as a C-style array. It is not related via +// inheritance to vnl_matrix. However, it can be converted cheaply to +// a vnl_matrix_ref. +// +// Read the overview documentation of vnl_vector_fixed. +// The text there applies here. +template +class vnl_matrix_fixed +{ + T data_[num_rows][num_cols]; // Local storage + + public: + typedef vnl_matrix_fixed self; + typedef size_t size_type; + + //: Construct an empty num_rows*num_cols matrix + vnl_matrix_fixed() = default; + //: Construct an m*n Matrix and copy rhs into it. + // Abort if rhs is not the same size. + vnl_matrix_fixed(const vnl_matrix_fixed& rhs) = default; + vnl_matrix_fixed(vnl_matrix_fixed&& other) = default; + //: Copy another vnl_matrix_fixed into this. + vnl_matrix_fixed& operator=(const vnl_matrix_fixed& rhs) = default; + vnl_matrix_fixed& operator=(vnl_matrix_fixed&& rhs) = default; + ~vnl_matrix_fixed() = default; + + + //: Construct an empty num_rows*num_cols matrix + // + // The sole purpose of this constructor is to match the interface of + // vnl_matrix, so that algorithms can template over the matrix type + // itself. It is illegal to call this constructor without + // n==num_rows and m==num_cols. + vnl_matrix_fixed( unsigned VXL_USED_IN_DEBUG(n), unsigned VXL_USED_IN_DEBUG(m) ) + { + assert( n == num_rows && m == num_cols ); + } + + //: Construct an m*n matrix and fill with value + explicit vnl_matrix_fixed(T value) + { + T* p = data_[0]; + unsigned int n = num_rows * num_cols; + while (n--) + *p++ = value; + } + + //: Construct an m*n Matrix and copy data into it row-wise. + explicit vnl_matrix_fixed(const T* datablck) + { + std::memcpy(data_[0], datablck, num_rows*num_cols*sizeof(T)); + } + + //: Construct an m*n Matrix and copy rhs into it. + // Abort if rhs is not the same size. + vnl_matrix_fixed(const vnl_matrix& rhs) + { + assert(rhs.rows() == num_rows && rhs.columns() == num_cols); + std::memcpy(data_[0], rhs.data_block(), num_rows*num_cols*sizeof(T)); + } + + + //: Set all elements to value v + // Complexity $O(r.c)$ + vnl_matrix_fixed& operator= (T const&v); + + //: Copy a vnl_matrix into this. + // Abort if rhs is not the same size. + vnl_matrix_fixed& operator=(const vnl_matrix& rhs); + +// Basic 2D-Array functionality------------------------------------------- + + //: Return the total number of elements stored by the matrix. + // This equals rows() * cols() + inline unsigned int size() const { return num_rows*num_cols; } + + //: Return the number of rows. + inline unsigned int rows() const { return num_rows; } + + //: Return the number of columns. + // A synonym for columns(). + inline unsigned int cols() const { return num_cols; } + + //: Return the number of columns. + // A synonym for cols(). + inline unsigned int columns() const { return num_cols; } + + //: set element + inline void put (unsigned r, unsigned c, T const& v) + { +#if VNL_CONFIG_CHECK_BOUNDS + if (r >= num_rows) // If invalid size specified + vnl_error_matrix_row_index("put", r); // Raise exception + if (c >= num_cols) // If invalid size specified + vnl_error_matrix_col_index("put", c); // Raise exception +#endif + this->data_[r][c] = v; + } + + //: get element + inline T get (unsigned r, unsigned c) const + { +#if VNL_CONFIG_CHECK_BOUNDS + if (r >= num_rows) // If invalid size specified + vnl_error_matrix_row_index("get", r); // Raise exception + if (c >= num_cols) // If invalid size specified + vnl_error_matrix_col_index("get", c); // Raise exception +#endif + return this->data_[r][c]; + } + + //: set element, and return *this + vnl_matrix_fixed& set (unsigned r, unsigned c, T const& v) { (*this)(r,c) = v; return *this; } + + //: return pointer to given row + // No boundary checking here. + T * operator[] (unsigned r) { return data_[r]; } + + //: return pointer to given row + // No boundary checking here. + T const * operator[] (unsigned r) const { return data_[r]; } + + //: Access an element for reading or writing + // There are assert style boundary checks - #define NDEBUG to turn them off. + T & operator() (unsigned r, unsigned c); + + //: Access an element for reading + // There are assert style boundary checks - #define NDEBUG to turn them off. + T const & operator() (unsigned r, unsigned c) const; + + // ----------------------- Filling and copying ----------------------- + + //: Sets all elements of matrix to specified value, and returns "*this". + // Complexity $O(r.c)$ + // Returning "*this" allows "chaining" two or more operations: + // e.g., to set a matrix to a column-normalized all-elements-equal matrix, say + // \code + // M.fill(1).normalize_columns(); + // \endcode + // Returning "*this" also allows passing such a matrix as argument + // to a function f, without having to name the constructed matrix: + // \code + // f(vnl_matrix_fixed(1.0).normalize_columns()); + // \endcode + vnl_matrix_fixed& fill(T); + + //: Sets all diagonal elements of matrix to specified value; returns "*this". + // Complexity $O(\min(r,c))$ + // Returning "*this" allows "chaining" two or more operations: + // e.g., to set a 3x3 matrix to [5 0 0][0 10 0][0 0 15], just say + // \code + // M.fill_diagonal(5).scale_row(1,2).scale_column(2,3); + // \endcode + // Returning "*this" also allows passing a diagonal-filled matrix as argument + // to a function f, without having to name the constructed matrix: + // \code + // f(vnl_matrix_fixed().fill_diagonal(5)); + // \endcode + vnl_matrix_fixed& fill_diagonal(T); + + //: Sets the diagonal elements of this matrix to the specified list of values. + // Returning "*this" allows "chaining" two or more operations: see the + // reasoning (and the examples) in the documentation for method + // fill_diagonal(). + vnl_matrix_fixed& set_diagonal(vnl_vector const&); + + //: Fills (laminates) this matrix with the given data, then returns it. + // We assume that the argument points to a contiguous rows*cols array, stored rowwise. + // No bounds checking on the array. + // Returning "*this" allows "chaining" two or more operations: + // e.g., to fill a square matrix column-wise, fill it rowwise then transpose: + // \code + // M.copy_in(array).inplace_transpose(); + // \endcode + // Returning "*this" also allows passing a filled-in matrix as argument + // to a function f, without having to name the constructed matrix: + // \code + // f(vnl_matrix_fixed().copy_in(array)); + // \endcode + vnl_matrix_fixed& copy_in(T const *); + + //: Fills (laminates) this matrix with the given data, then returns it. + // A synonym for copy_in() + vnl_matrix_fixed& set(T const *d) { return copy_in(d); } + + //: Fills the given array with this matrix. + // We assume that the argument points to a contiguous rows*cols array, stored rowwise. + // No bounds checking on the array. + void copy_out(T *) const; + + //: Transposes this matrix efficiently, if it is square, and returns it. + // Returning "*this" allows "chaining" two or more operations: + // e.g., to fill a square matrix column-wise, fill it rowwise then transpose: + // \code + // M.copy_in(array).inplace_transpose(); + // \endcode + vnl_matrix_fixed& inplace_transpose(); + + // ----------------------- Arithmetic -------------------------------- + // note that these functions should not pass scalar as a const&. + // Look what would happen to A /= A(0,0). + + //: Add \a s to each element of lhs matrix in situ + vnl_matrix_fixed& operator+= (T s) + { + self::add( data_block(), s, data_block() ); return *this; + } + + //: Subtract \a s from each element of lhs matrix in situ + vnl_matrix_fixed& operator-= (T s) + { + self::sub( data_block(), s, data_block() ); return *this; + } + + //: + vnl_matrix_fixed& operator*= (T s) + { + self::mul( data_block(), s, data_block() ); return *this; + } + + //: + vnl_matrix_fixed& operator/= (T s) + { + self::div( data_block(), s, data_block() ); return *this; + } + + //: + vnl_matrix_fixed& operator+= (vnl_matrix_fixed const& m) + { + self::add( data_block(), m.data_block(), data_block() ); return *this; + } + + //: + vnl_matrix_fixed& operator+= (vnl_matrix const& m) + { + assert( m.rows() == rows() && m.cols() == cols() ); + self::add( data_block(), m.data_block(), data_block() ); return *this; + } + + //: + vnl_matrix_fixed& operator-= (vnl_matrix_fixed const& m) + { + self::sub( data_block(), m.data_block(), data_block() ); return *this; + } + + //: + vnl_matrix_fixed& operator-= (vnl_matrix const& m) + { + assert( m.rows() == rows() && m.cols() == cols() ); + self::sub( data_block(), m.data_block(), data_block() ); + return *this; + } + + //: Negate all elements of matrix + vnl_matrix_fixed operator- () const + { + vnl_matrix_fixed r; + self::sub( T(0), data_block(), r.data_block() ); + return r; + } + + //: + vnl_matrix_fixed& operator*= (vnl_matrix_fixed const& s) + { + vnl_matrix_fixed out; + for (unsigned i = 0; i < num_rows; ++i) + for (unsigned j = 0; j < num_cols; ++j) + { + T accum = this->data_[i][0] * s(0,j); + for (unsigned k = 1; k < num_cols; ++k) + accum += this->data_[i][k] * s(k,j); + out(i,j) = accum; + } + return *this = out; + } + + ////--------------------------- Additions ---------------------------- + + //: Make a new matrix by applying function to each element. + vnl_matrix_fixed apply(T (*f)(T)) const; + + //: Make a new matrix by applying function to each element. + vnl_matrix_fixed apply(T (*f)(T const&)) const; + + //: Make a vector by applying a function across rows. + vnl_vector_fixed apply_rowwise(T (*f)(vnl_vector_fixed const&)) const; + + //: Make a vector by applying a function across columns. + vnl_vector_fixed apply_columnwise(T (*f)(vnl_vector_fixed const&)) const; + + //: Return transpose + vnl_matrix_fixed transpose() const; + + //: Return conjugate transpose + vnl_matrix_fixed conjugate_transpose() const; + + //: Set values of this matrix to those of M, starting at [top,left] + vnl_matrix_fixed& update(vnl_matrix const&, unsigned top=0, unsigned left=0); + + //: Set the elements of the i'th column to v[i] (No bounds checking) + vnl_matrix_fixed& set_column(unsigned i, T const * v); + + //: Set the elements of the i'th column to value, then return *this. + vnl_matrix_fixed& set_column(unsigned i, T value ); + + //: Set j-th column to v, then return *this. + vnl_matrix_fixed& set_column(unsigned j, vnl_vector const& v); + + //: Set j-th column to v, then return *this. + vnl_matrix_fixed& set_column(unsigned j, vnl_vector_fixed const& v); + + //: Set columns to those in M, starting at starting_column, then return *this. + vnl_matrix_fixed& set_columns(unsigned starting_column, vnl_matrix const& M); + + //: Set the elements of the i'th row to v[i] (No bounds checking) + vnl_matrix_fixed& set_row (unsigned i, T const * v); + + //: Set the elements of the i'th row to value, then return *this. + vnl_matrix_fixed& set_row (unsigned i, T value ); + + //: Set the i-th row, then return *this. + vnl_matrix_fixed& set_row (unsigned i, vnl_vector const&); + + //: Set the i-th row, then return *this. + vnl_matrix_fixed& set_row (unsigned i, vnl_vector_fixed const&); + + //: Extract a sub-matrix of size r x c, starting at (top,left) + // Thus it contains elements [top,top+r-1][left,left+c-1] + vnl_matrix extract (unsigned r, unsigned c, + unsigned top=0, unsigned left=0) const; + + //: Extract a sub-matrix starting at (top,left) + // + // The output is stored in \a sub_matrix, and it should have the + // required size on entry. Thus the result will contain elements + // [top,top+sub_matrix.rows()-1][left,left+sub_matrix.cols()-1] + void extract ( vnl_matrix& sub_matrix, + unsigned top=0, unsigned left=0) const; + + //: Get a vector equal to the given row + vnl_vector_fixed get_row (unsigned row) const; + + //: Get a vector equal to the given column + vnl_vector_fixed get_column(unsigned col) const; + + //: Get a matrix composed of rows from the indices specified in the supplied vector. + vnl_matrix get_rows(vnl_vector i) const; + + //: Get a matrix composed of columns from the indices specified in the supplied vector. + vnl_matrix get_columns(vnl_vector i) const; + + //: Get n rows beginning at rowstart + vnl_matrix get_n_rows (unsigned rowstart, unsigned n) const; + + //: Get n columns beginning at colstart + vnl_matrix get_n_columns(unsigned colstart, unsigned n) const; + + //: Return a vector with the content of the (main) diagonal + vnl_vector get_diagonal() const; + + //: Flatten row-major (C-style) + vnl_vector_fixed flatten_row_major() const; + + //: Flatten column-major (Fortran-style) + vnl_vector_fixed flatten_column_major() const; + + // ==== mutators ==== + + //: Sets this matrix to an identity matrix, then returns "*this". + // Returning "*this" allows e.g. passing an identity matrix as argument to + // a function f, without having to name the constructed matrix: + // \code + // f(vnl_matrix_fixed().set_identity()); + // \endcode + // Returning "*this" also allows "chaining" two or more operations: + // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say + // \code + // M.set_identity().scale_row(0,3).scale_column(1,2); + // \endcode + // If the matrix is not square, anyhow set main diagonal to 1, the rest to 0. + vnl_matrix_fixed& set_identity(); + + //: Reverses the order of rows, and returns "*this". + // Returning "*this" allows "chaining" two or more operations: + // e.g., to flip both up-down and left-right, one could just say + // \code + // M.flipud().fliplr(); + // \endcode + vnl_matrix_fixed& flipud(); + + //: Reverses the order of columns, and returns "*this". + // Returning "*this" allows "chaining" two or more operations: + // e.g., to flip both up-down and left-right, one could just say + // \code + // M.flipud().fliplr(); + // \endcode + vnl_matrix_fixed& fliplr(); + + //: Normalizes each row so it is a unit vector, and returns "*this". + // Zero rows are not modified + // Returning "*this" allows "chaining" two or more operations: + // e.g., to set a matrix to a row-normalized all-elements-equal matrix, say + // \code + // M.fill(1).normalize_rows(); + // \endcode + // Returning "*this" also allows passing such a matrix as argument + // to a function f, without having to name the constructed matrix: + // \code + // f(vnl_matrix_fixed(1.0).normalize_rows()); + // \endcode + vnl_matrix_fixed& normalize_rows(); + + //: Normalizes each column so it is a unit vector, and returns "*this". + // Zero columns are not modified + // Returning "*this" allows "chaining" two or more operations: + // e.g., to set a matrix to a column-normalized all-elements-equal matrix, say + // \code + // M.fill(1).normalize_columns(); + // \endcode + // Returning "*this" also allows passing such a matrix as argument + // to a function f, without having to name the constructed matrix: + // \code + // f(vnl_matrix_fixed(1.0).normalize_columns()); + // \endcode + vnl_matrix_fixed& normalize_columns(); + + //: Scales elements in given row by a factor T, and returns "*this". + // Returning "*this" allows "chaining" two or more operations: + // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say + // \code + // M.set_identity().scale_row(0,3).scale_column(1,2); + // \endcode + vnl_matrix_fixed& scale_row (unsigned row, T value); + + //: Scales elements in given column by a factor T, and returns "*this". + // Returning "*this" allows "chaining" two or more operations: + // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say + // \code + // M.set_identity().scale_row(0,3).scale_column(1,2); + // \endcode + vnl_matrix_fixed& scale_column(unsigned col, T value); + + //: Swap this matrix with that matrix + void swap(vnl_matrix_fixed & that); + + //: Type def for norms. + typedef typename vnl_c_vector::abs_t abs_t; + + //: Return sum of absolute values of elements + abs_t array_one_norm() const { return vnl_c_vector::one_norm(begin(), size()); } + + //: Return square root of sum of squared absolute element values + abs_t array_two_norm() const { return vnl_c_vector::two_norm(begin(), size()); } + + //: Return largest absolute element value + abs_t array_inf_norm() const { return vnl_c_vector::inf_norm(begin(), size()); } + + //: Return sum of absolute values of elements + abs_t absolute_value_sum() const { return array_one_norm(); } + + //: Return largest absolute value + abs_t absolute_value_max() const { return array_inf_norm(); } + + // $ || M ||_1 := \max_j \sum_i | M_{ij} | $ + abs_t operator_one_norm() const; + + // $ || M ||_\inf := \max_i \sum_j | M_{ij} | $ + abs_t operator_inf_norm() const; + + //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements) + abs_t frobenius_norm() const { return vnl_c_vector::two_norm(begin(), size()); } + + //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements) + abs_t fro_norm() const { return frobenius_norm(); } + + //: Return RMS of all elements + abs_t rms() const { return vnl_c_vector::rms_norm(begin(), size()); } + + //: Return minimum value of elements + T min_value() const { return vnl_c_vector::min_value(begin(), size()); } + + //: Return maximum value of elements + T max_value() const { return vnl_c_vector::max_value(begin(), size()); } + + //: Return location of minimum value of elements + unsigned arg_min() const { return vnl_c_vector::arg_min(begin(), size()); } + + //: Return location of maximum value of elements + unsigned arg_max() const { return vnl_c_vector::arg_max(begin(), size()); } + + //: Return mean of all matrix elements + T mean() const { return vnl_c_vector::mean(begin(), size()); } + + // predicates + + //: Return true iff the size is zero. + bool empty() const { return num_rows==0 && num_cols==0; } + + //: Return true if all elements equal to identity. + bool is_identity() const; + + //: Return true if all elements equal to identity, within given tolerance + bool is_identity(double tol) const; + + //: Return true if all elements equal to zero. + bool is_zero() const; + + //: Return true if all elements equal to zero, within given tolerance + bool is_zero(double tol) const; + + //: Return true if all elements of both matrices are equal, within given tolerance + bool is_equal(vnl_matrix_fixed const& rhs, double tol) const; + + //: Return true if finite + bool is_finite() const; + + //: Return true if matrix contains NaNs + bool has_nans() const; + + //: abort if size is not as expected + // This function does or tests nothing if NDEBUG is defined + void assert_size(unsigned VXL_USED_IN_DEBUG(nr_rows), unsigned VXL_USED_IN_DEBUG(nr_cols) ) const + { +#ifndef NDEBUG + assert_size_internal(nr_rows, nr_cols); +#endif + } + + //: abort if matrix contains any INFs or NANs. + // This function does or tests nothing if NDEBUG is defined + void assert_finite() const + { +#ifndef NDEBUG + assert_finite_internal(); +#endif + } + + ////----------------------- Input/Output ---------------------------- + + // : Read a vnl_matrix from an ascii std::istream, automatically determining file size if the input matrix has zero size. + bool read_ascii(std::istream& s); + + //-------------------------------------------------------------------------------- + + //: Access the contiguous block storing the elements in the matrix row-wise. O(1). + // 1d array, row-major order. + T const* data_block() const; + + //: Access the contiguous block storing the elements in the matrix row-wise. O(1). + // 1d array, row-major order. + T * data_block(); + + + //---------------------------------------------------------------------- + // Conversion to vnl_matrix_ref. + + // The const version of as_ref should return a const vnl_matrix_ref + // so that the vnl_matrix_ref::non_const() cannot be used on + // it. This prevents a const vnl_matrix_fixed from being cast into a + // non-const vnl_matrix reference, giving a slight increase in type safety. + + //: Explicit conversion to a vnl_matrix_ref. + // This is a cheap conversion for those functions that have an interface + // for vnl_matrix but not for vnl_matrix_fixed. There is also a + // conversion operator that should work most of the time. + // \sa vnl_matrix_ref::non_const + inline vnl_matrix_ref as_ref() { return vnl_matrix_ref( num_rows, num_cols, data_block() ); } + + //: Explicit conversion to a vnl_matrix_ref. + // This is a cheap conversion for those functions that have an interface + // for vnl_matrix but not for vnl_matrix_fixed. There is also a + // conversion operator that should work most of the time. + // \sa vnl_matrix_ref::non_const + inline const vnl_matrix_ref as_ref() const { return vnl_matrix_ref( num_rows, num_cols, const_cast(data_block()) ); } + + //: Cheap conversion to vnl_matrix_ref + // Sometimes, such as with templated functions, the compiler cannot + // use this user-defined conversion. For those cases, use the + // explicit as_ref() method instead. + inline operator const vnl_matrix_ref() const { return vnl_matrix_ref( num_rows, num_cols, const_cast(data_block()) ); } + + //: Convert to a vnl_matrix. + inline const vnl_matrix as_matrix() const { return vnl_matrix(const_cast(data_block()),num_rows,num_cols); } + + //---------------------------------------------------------------------- + + typedef T element_type; + + //: Iterators + typedef T *iterator; + //: Iterator pointing to start of data + inline iterator begin() { return data_[0]; } + //: Iterator pointing to element beyond end of data + inline iterator end() { return begin() + size(); } + + //: Const iterators + typedef T const *const_iterator; + //: Iterator pointing to start of data + inline const_iterator begin() const { return data_[0]; } + //: Iterator pointing to element beyond end of data + inline const_iterator end() const { return begin() + size(); } + + //-------------------------------------------------------------------------------- + + //: Return true if *this == rhs + bool operator_eq (vnl_matrix_fixed const & rhs) const + { + return equal( this->data_block(), rhs.data_block() ); + } + + //: Equality operator + bool operator==(vnl_matrix_fixed const &that) const { return this->operator_eq(that); } + + //: Inequality operator + bool operator!=(vnl_matrix_fixed const &that) const { return !this->operator_eq(that); } + + //: Equality operator + bool operator==(vnl_matrix const &that) const { return this->operator_eq(that); } + + //: Inequality operator + bool operator!=(vnl_matrix const &that) const { return !this->operator_eq(that); } + + //: Print matrix to os in some hopefully sensible format + void print(std::ostream& os) const; + +//-------------------------------------------------------------------------------- + + + // Helper routines for arithmetic. These routines know the size from + // the template parameters. The vector-vector operations are + // element-wise. + + static void add( const T* a, const T* b, T* r ); + static void add( const T* a, T b, T* r ); + static void sub( const T* a, const T* b, T* r ); + static void sub( const T* a, T b, T* r ); + static void sub( T a, const T* b, T* r ); + static void mul( const T* a, const T* b, T* r ); + static void mul( const T* a, T b, T* r ); + static void div( const T* a, const T* b, T* r ); + static void div( const T* a, T b, T* r ); + + static bool equal( const T* a, const T* b ); + + private: + void assert_finite_internal() const; + + void assert_size_internal(unsigned, unsigned) const; +}; + +// Make the operators below inline because (1) they are small and +// (2) we then have less explicit instantiation trouble. + + +// --- Matrix-scalar ------------------------------------------------------------- + +template +inline +vnl_matrix_fixed operator+( const vnl_matrix_fixed& mat1, const vnl_matrix_fixed& mat2 ) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::add( mat1.data_block(), mat2.data_block(), r.data_block() ); + return r; +} + +template +inline +vnl_matrix_fixed operator+( const vnl_matrix_fixed& mat, T s ) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::add( mat.data_block(), s, r.data_block() ); + return r; +} + +template +inline +vnl_matrix_fixed operator+( const T& s, + const vnl_matrix_fixed& mat ) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::add( mat.data_block(), s, r.data_block() ); + return r; +} + +template +inline +vnl_matrix_fixed operator-( const vnl_matrix_fixed& mat1, const vnl_matrix_fixed& mat2 ) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::sub( mat1.data_block(), mat2.data_block(), r.data_block() ); + return r; +} + +template +inline +vnl_matrix_fixed operator-( const vnl_matrix_fixed& mat, T s ) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::sub( mat.data_block(), s, r.data_block() ); + return r; +} + +template +inline +vnl_matrix_fixed operator-( const T& s, + const vnl_matrix_fixed& mat ) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::sub( s, mat.data_block(), r.data_block() ); + return r; +} + +template +inline +vnl_matrix_fixed operator*( const vnl_matrix_fixed& mat, T s ) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::mul( mat.data_block(), s, r.data_block() ); + return r; +} + +template +inline +vnl_matrix_fixed operator*( const T& s, + const vnl_matrix_fixed& mat ) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::mul( mat.data_block(), s, r.data_block() ); + return r; +} + +template +inline +vnl_matrix_fixed operator/( const vnl_matrix_fixed& mat, T s ) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::div( mat.data_block(), s, r.data_block() ); + return r; +} + + +template +inline +vnl_matrix_fixed element_product( const vnl_matrix_fixed& mat1, + const vnl_matrix_fixed& mat2 ) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::mul( mat1.data_block(), mat2.data_block(), r.data_block() ); + return r; +} + + +template +inline +vnl_matrix_fixed element_quotient( const vnl_matrix_fixed& mat1, + const vnl_matrix_fixed& mat2) +{ + vnl_matrix_fixed r; + vnl_matrix_fixed::div( mat1.data_block(), mat2.data_block(), r.data_block() ); + return r; +} + + +// The following two functions are helper functions keep the +// matrix-matrix and matrix-vector multiplication code in one place, +// so that bug fixes, etc, can be localized. +template +inline +vnl_vector_fixed +vnl_matrix_fixed_mat_vec_mult(const vnl_matrix_fixed& a, + const vnl_vector_fixed& b) +{ + vnl_vector_fixed out; + for (unsigned i = 0; i < M; ++i) + { + T accum = a(i,0) * b(0); + for (unsigned k = 1; k < N; ++k) + accum += a(i,k) * b(k); + out(i) = accum; + } + return out; +} + +template +inline +vnl_vector_fixed +vnl_matrix_fixed_vec_mat_mult(const vnl_vector_fixed& a, + const vnl_matrix_fixed& b) +{ + vnl_vector_fixed out; + for (unsigned i = 0; i < N; ++i) + { + T accum = a(0) * b(0,i); + for (unsigned k = 1; k < M; ++k) + accum += a(k) * b(k,i); + out(i) = accum; + } + return out; +} + +// see comment above +template +inline +vnl_matrix_fixed +vnl_matrix_fixed_mat_mat_mult(const vnl_matrix_fixed& a, + const vnl_matrix_fixed& b) +{ + vnl_matrix_fixed out; + for (unsigned i = 0; i < M; ++i) + for (unsigned j = 0; j < O; ++j) + { + T accum = a(i,0) * b(0,j); + for (unsigned k = 1; k < N; ++k) + accum += a(i,k) * b(k,j); + out(i,j) = accum; + } + return out; +} + +// The version for correct compilers + +//: Multiply conformant vnl_matrix_fixed (M x N) and vector_fixed (N) +// \relatesalso vnl_vector_fixed +// \relatesalso vnl_matrix_fixed +template +inline +vnl_vector_fixed operator*(const vnl_matrix_fixed& a, const vnl_vector_fixed& b) +{ + return vnl_matrix_fixed_mat_vec_mult(a, b); +} + +//: Multiply conformant vector_fixed (M) and vnl_matrix_fixed (M x N) +// \relatesalso vnl_vector_fixed +// \relatesalso vnl_matrix_fixed +template +inline +vnl_vector_fixed operator*(const vnl_vector_fixed& a, const vnl_matrix_fixed& b) +{ + return vnl_matrix_fixed_vec_mat_mult(a, b); +} + +//: Multiply two conformant vnl_matrix_fixed (M x N) times (N x O) +// \relatesalso vnl_matrix_fixed +template +inline +vnl_matrix_fixed operator*(const vnl_matrix_fixed& a, const vnl_matrix_fixed& b) +{ + return vnl_matrix_fixed_mat_mat_mult(a, b); +} + + +// These overloads for the common case of mixing a fixed with a +// non-fixed. Because the operator* are templated, the fixed will not +// be automatically converted to a non-fixed-ref. These do it for you. + +template +inline vnl_matrix operator+( const vnl_matrix_fixed& a, const vnl_matrix& b ) +{ + return a.as_ref() + b; +} + +template +inline vnl_matrix operator+( const vnl_matrix& a, const vnl_matrix_fixed& b ) +{ + return a + b.as_ref(); +} + +template +inline vnl_matrix operator-( const vnl_matrix_fixed& a, const vnl_matrix& b ) +{ + return a.as_ref() - b; +} + +template +inline vnl_matrix operator-( const vnl_matrix& a, const vnl_matrix_fixed& b ) +{ + return a - b.as_ref(); +} + +template +inline vnl_matrix operator*( const vnl_matrix_fixed& a, const vnl_matrix& b ) +{ + return a.as_ref() * b; +} + +template +inline vnl_matrix operator*( const vnl_matrix& a, const vnl_matrix_fixed& b ) +{ + return a * b.as_ref(); +} + +template +inline vnl_vector operator*( const vnl_matrix_fixed& a, const vnl_vector& b ) +{ + return a.as_ref() * b; +} + +template +inline vnl_vector operator*( const vnl_matrix& a, const vnl_vector_fixed& b ) +{ + return a * b.as_ref(); +} + + +// --- I/O operations ------------------------------------------------------------ + +template +inline +std::ostream& operator<< (std::ostream& os, vnl_matrix_fixed const& mat) +{ + mat.print(os); + return os; +} + +template +inline +std::istream& operator>> (std::istream& is, vnl_matrix_fixed& mat) +{ + mat.read_ascii(is); + return is; +} + +//: +// \relatesalso vnl_vector_fixed +template VNL_EXPORT +vnl_matrix_fixed outer_product(vnl_vector_fixed const& a, vnl_vector_fixed const& b); + +#define VNL_MATRIX_FIXED_INSTANTIATE(T, M, N) \ +extern "please include vnl/vnl_matrix_fixed.hxx instead" + +#endif // vnl_matrix_fixed_h_ diff --git a/Patches/VXL/vnl_transpose.h b/Patches/VXL/vnl_transpose.h new file mode 100644 index 00000000..5108e70d --- /dev/null +++ b/Patches/VXL/vnl_transpose.h @@ -0,0 +1,77 @@ +// This is core/vnl/vnl_transpose.h +#ifndef vnl_transpose_h_ +#define vnl_transpose_h_ +//: +// \file +// \brief Efficient matrix transpose +// \author Andrew W. Fitzgibbon, Oxford RRG +// \date 23 Dec 96 +// +// \verbatim +// Modifications +// LSB (Manchester) 19/3/01 Tidied documentation +// \endverbatim + +#include +#ifdef _MSC_VER +# include +#endif +#include +#include "vnl/vnl_export.h" + +//: Efficient matrix transpose +// vnl_transpose is an efficient way to write C = vnl_transpose(A) * B. +// The vnl_transpose class holds a reference to the original matrix +// and when involved in an operation for which it has been specialized, +// performs the operation without copying. +// +// If the operation has not been specialized, the vnl_transpose performs +// a copying conversion to a matrix, printing a message to stdout. +// At that stage, the user may choose to implement the particular operation +// or use vnl_transpose::asMatrix() to clear the warning. +// +// NOTE: This is a reference class, so should be shorter-lived than the +// matrix to which it refers. +// +// NOTE: This only works for arguments of type vnl_matrix + +class vnl_transpose +{ + const vnl_matrix& M_; + public: + + //: Make a vnl_transpose object referring to matrix M + vnl_transpose(const vnl_matrix& M): M_(M) {} + + //: Noisily convert a vnl_transpose to a matrix + operator vnl_matrix () const { + std::cerr << "vnl_transpose being converted to matrix -- help! I don't wanna go!\n"; + return M_.transpose(); + } + + //: Quietly convert a vnl_transpose to a matrix + vnl_matrix asMatrix () const { return M_.transpose(); } + + //: Return M' * O + vnl_matrix operator* (const vnl_matrix& O) { + vnl_matrix ret(M_.columns(), O.columns()); + vnl_fastops::AtB(ret, M_, O); + return ret; + } + + //: Return M' * O + vnl_vector operator* (const vnl_vector& O) { + vnl_vector ret(M_.columns()); + vnl_fastops::AtB(ret, M_, O); + return ret; + } + + //: Return A * B' + friend vnl_matrix operator* (const vnl_matrix& A, const vnl_transpose& B) { + vnl_matrix ret(A.rows(), B.M_.rows()); + vnl_fastops::ABt(ret, A, B.M_); + return ret; + } +}; + +#endif // vnl_transpose_h_ From 2d5bd160bc4c64a192a56077e63944e815915af8 Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Sun, 10 Feb 2019 20:00:56 -0600 Subject: [PATCH 14/22] Update patch --- Patches/VXL/Patch.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Patches/VXL/Patch.cmake b/Patches/VXL/Patch.cmake index 21ed9ada..9e619803 100644 --- a/Patches/VXL/Patch.cmake +++ b/Patches/VXL/Patch.cmake @@ -13,7 +13,7 @@ file(COPY ${VXL_patch}//vnl_matrix_fixed.h DESTINATION ${VXL_source}/core/vnl/ ) -file(COPY ${VXL_patch}//vnl_io_matrix.h +file(COPY ${VXL_patch}//vnl_transpose.h DESTINATION ${VXL_source}/core/vnl/ ) From ceb52604184833dfc55850628f2e6d18e427457d Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Fri, 12 Jul 2019 17:22:36 -0400 Subject: [PATCH 15/22] Update ITK hash --- CMake/fletch-tarballs.cmake | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CMake/fletch-tarballs.cmake b/CMake/fletch-tarballs.cmake index 8308a998..04209066 100644 --- a/CMake/fletch-tarballs.cmake +++ b/CMake/fletch-tarballs.cmake @@ -436,10 +436,9 @@ set(VXL_dlname "vxl-${VXL_version}.zip") list(APPEND fletch_external_sources VXL) # ITK -set(ITK_version 5.0) -set(ITK_minor b03) -set(ITK_url "https://github.com/InsightSoftwareConsortium/ITK/archive/v${ITK_version}${ITK_minor}.tar.gz") -set(ITK_md5 "84d10e1d6324c1c1250ac4ecfcc1b403") +set(ITK_version fc688e7a2c89967e3d6cbb779f87ec37a4e4750b) +set(ITK_url "https://github.com/InsightSoftwareConsortium/ITK/archive/v${ITK_version}.tar.gz") +set(ITK_md5 "692eadb04353e69cf23f5197a9cd4c72") set(ITK_experimental TRUE) list(APPEND fletch_external_sources ITK) From de998ccfb7ff80cac0ff4a44727971d58ce9f32c Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Fri, 12 Jul 2019 17:43:33 -0400 Subject: [PATCH 16/22] Update hash --- CMake/fletch-tarballs.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMake/fletch-tarballs.cmake b/CMake/fletch-tarballs.cmake index 04209066..b7f08a3d 100644 --- a/CMake/fletch-tarballs.cmake +++ b/CMake/fletch-tarballs.cmake @@ -436,9 +436,9 @@ set(VXL_dlname "vxl-${VXL_version}.zip") list(APPEND fletch_external_sources VXL) # ITK -set(ITK_version fc688e7a2c89967e3d6cbb779f87ec37a4e4750b) -set(ITK_url "https://github.com/InsightSoftwareConsortium/ITK/archive/v${ITK_version}.tar.gz") -set(ITK_md5 "692eadb04353e69cf23f5197a9cd4c72") +set(ITK_version "fc688e7a2c89967e3d6cbb779f87ec37a4e4750b") +set(ITK_url "https://github.com/InsightSoftwareConsortium/ITK/archive/${ITK_version}.tar.gz") +set(ITK_md5 "8f0965e5ac7828a273dfff8d3b81ff9a") set(ITK_experimental TRUE) list(APPEND fletch_external_sources ITK) From ac4e6a60e927f8ede27449157ac28e31093a60df Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Mon, 22 Jul 2019 16:02:04 -0400 Subject: [PATCH 17/22] Revert "Update patch" This reverts commit 2d5bd160bc4c64a192a56077e63944e815915af8. --- Patches/VXL/Patch.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Patches/VXL/Patch.cmake b/Patches/VXL/Patch.cmake index 9e619803..21ed9ada 100644 --- a/Patches/VXL/Patch.cmake +++ b/Patches/VXL/Patch.cmake @@ -13,7 +13,7 @@ file(COPY ${VXL_patch}//vnl_matrix_fixed.h DESTINATION ${VXL_source}/core/vnl/ ) -file(COPY ${VXL_patch}//vnl_transpose.h +file(COPY ${VXL_patch}//vnl_io_matrix.h DESTINATION ${VXL_source}/core/vnl/ ) From ed3ef1a00bc7ebea6b826101c71358cc22566f8c Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Mon, 22 Jul 2019 16:02:12 -0400 Subject: [PATCH 18/22] Revert "Add patch for windows linking issues" This reverts commit d5bbf06fcd8d9d34057f0623ae2f3162f1371049. --- Patches/VXL/Patch.cmake | 12 - Patches/VXL/vnl_io_matrix.hxx | 99 --- Patches/VXL/vnl_matrix_fixed.h | 1027 -------------------------------- Patches/VXL/vnl_transpose.h | 77 --- 4 files changed, 1215 deletions(-) delete mode 100644 Patches/VXL/vnl_io_matrix.hxx delete mode 100644 Patches/VXL/vnl_matrix_fixed.h delete mode 100644 Patches/VXL/vnl_transpose.h diff --git a/Patches/VXL/Patch.cmake b/Patches/VXL/Patch.cmake index 21ed9ada..1e4b7c8e 100644 --- a/Patches/VXL/Patch.cmake +++ b/Patches/VXL/Patch.cmake @@ -8,15 +8,3 @@ message("Patching VXL in ${VXL_source}") file(COPY ${VXL_patch}//vidl_ffmpeg_ostream_v56.hxx DESTINATION ${VXL_source}/core/vidl/ ) - -file(COPY ${VXL_patch}//vnl_matrix_fixed.h - DESTINATION ${VXL_source}/core/vnl/ -) - -file(COPY ${VXL_patch}//vnl_io_matrix.h - DESTINATION ${VXL_source}/core/vnl/ -) - -file(COPY ${VXL_patch}//vnl_io_matrix.hxx - DESTINATION ${VXL_source}/core/vnl/io/ -) diff --git a/Patches/VXL/vnl_io_matrix.hxx b/Patches/VXL/vnl_io_matrix.hxx deleted file mode 100644 index 1ecbbd76..00000000 --- a/Patches/VXL/vnl_io_matrix.hxx +++ /dev/null @@ -1,99 +0,0 @@ -// This is core/vnl/io/vnl_io_matrix.hxx -#ifndef vnl_io_matrix_hxx_ -#define vnl_io_matrix_hxx_ -//: -// \file - -#include "vnl_io_matrix.h" -#include -#include -#include -#include - -//================================================================================= -//: Binary save self to stream. -template -void vsl_b_write(vsl_b_ostream & os, const vnl_matrix & p) -{ - constexpr short version_no = 2; - vsl_b_write(os, version_no); - vsl_b_write(os, p.rows()); - vsl_b_write(os, p.cols()); - - // Calling p.begin() on empty matrix causes segfault - if (p.size()>0) - vsl_block_binary_write(os, p.begin(), p.size()); -} - -//================================================================================= -//: Binary load self from stream. -template -void vsl_b_read(vsl_b_istream &is, vnl_matrix & p) -{ - if (!is) return; - - short v; - unsigned m, n; - vsl_b_read(is, v); - switch (v) - { - case 1: - vsl_b_read(is, m); - vsl_b_read(is, n); - p.set_size(m, n); - // Calling begin() on empty matrix causes segfault - if (m*n>0) - vsl_b_read_block_old(is, p.begin(), p.size()); - break; - - case 2: - vsl_b_read(is, m); - vsl_b_read(is, n); - p.set_size(m, n); - // Calling begin() on empty matrix causes segfault - if (m*n>0) - vsl_block_binary_read(is, p.data_block(), p.size()); - break; - - default: - std::cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, vnl_matrix&)\n" - << " Unknown version number "<< v << '\n'; - is.is().clear(std::ios::badbit); // Set an unrecoverable IO error on stream - return; - } -} - -//==================================================================================== -//: Output a human readable summary to the stream -template -void vsl_print_summary(std::ostream & os,const vnl_matrix & p) -{ - os<<"Size: "<p.rows()) m=p.rows(); - if (n>p.cols()) n=p.cols(); - - vsl_indent_inc(os); - for (unsigned int i=0;in) os<<"..."; - os<<")\n"; - } - if (p.rows()>m) os < &); \ -template void vsl_b_read(vsl_b_istream &, vnl_matrix &); \ -template void vsl_b_write(vsl_b_ostream &, const vnl_matrix &) - -#endif // vnl_io_matrix_hxx_ diff --git a/Patches/VXL/vnl_matrix_fixed.h b/Patches/VXL/vnl_matrix_fixed.h deleted file mode 100644 index 8008fd9b..00000000 --- a/Patches/VXL/vnl_matrix_fixed.h +++ /dev/null @@ -1,1027 +0,0 @@ -// This is core/vnl/vnl_matrix_fixed.h -#ifndef vnl_matrix_fixed_h_ -#define vnl_matrix_fixed_h_ -//: -// \file -// \brief fixed size matrix -// -// \author Andrew W. Fitzgibbon, Oxford RRG -// \date 04 Aug 96 -// -// \verbatim -// Modifications -// Peter Vanroose, 23 Nov 1996: added explicit copy constructor -// LSB (Manchester) 15/03/2001: added Binary I/O and tidied up the documentation -// Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line -// Oct.2002 - Amitha Perera - separated vnl_matrix and vnl_matrix_fixed, -// removed necessity for vnl_matrix_fixed_ref -// Oct.2002 - Peter Vanroose - added inplace_transpose() method -// Jul.2003 - Paul Smyth - fixed end() bug, made op*=() more general -// Mar.2009 - Peter Vanroose - added arg_min() and arg_max() -// Oct.2010 - Peter Vanroose - mutators and filling methods now return *this -// Jan.2011 - Peter Vanroose - added methods set_diagonal() & get_diagonal() -// \endverbatim -//----------------------------------------------------------------------------- - -#include -#include -#include -#include -#ifdef _MSC_VER -# include -#endif - -#include "vnl_matrix.h" -#include "vnl_matrix_ref.h" -#include -#include // needed for e.g. vnl_matrix_fixed_mat_vec_mult() -#include -#include // for VNL_CONFIG_CHECK_BOUNDS -#include "vnl/vnl_export.h" - -template class vnl_matrix_fixed; - -// This mess is for a MSVC6 workaround. -// -// The problem: the matrix-matrix operator* should be written as a -// non-member function since vxl (currently) forbids the use of member -// templates. However, when declared as -// \code -// template -// matrix operator*( matrix, matrix ); -// \endcode -// MSVC6 does not find it. A solution is to declare it as a member -// template. However, the obvious -// \code -// template -// matrix operator*( matrix ); -// \endcode -// causes an internal compiler error. It turns out that if the new -// template parameter "o" comes _first_, then all is okay. Now, we -// can't change the signature of vnl_matrix_fixed to , so we use a "hidden" helper matrix. Except -// that user defined conversion operators and conversion constructors -// are not called for templated functions. So we have to use a helper -// base class. The base class is empty, which means that there is no -// loss in space or time efficiency. Finally, we have: -// \code -// template -// class fake_base { }; -// -// template -// class matrix : public fake_base -// { -// template -// matrix operator*( fake_base ); -// }; -// \endcode -// Notice how "o" is first in the list of template parameters. Since -// base class conversions _are_ performed during template matching, -// matrix is matched as fake_base, and all is good. For -// some values of good. -// -// Of course, all this trickery is pre-processed away for conforming -// compilers. -// -template -class vnl_matrix_fixed; -template -inline -vnl_vector_fixed vnl_matrix_fixed_mat_vec_mult(const vnl_matrix_fixed& a, const vnl_vector_fixed& b); -template -inline -vnl_matrix_fixed vnl_matrix_fixed_mat_mat_mult(const vnl_matrix_fixed& a, const vnl_matrix_fixed& b); - -//: Fixed size, stack-stored, space-efficient matrix. -// vnl_matrix_fixed is a fixed-length, stack storage vector. It has -// the same storage size as a C-style array. It is not related via -// inheritance to vnl_matrix. However, it can be converted cheaply to -// a vnl_matrix_ref. -// -// Read the overview documentation of vnl_vector_fixed. -// The text there applies here. -template -class vnl_matrix_fixed -{ - T data_[num_rows][num_cols]; // Local storage - - public: - typedef vnl_matrix_fixed self; - typedef size_t size_type; - - //: Construct an empty num_rows*num_cols matrix - vnl_matrix_fixed() = default; - //: Construct an m*n Matrix and copy rhs into it. - // Abort if rhs is not the same size. - vnl_matrix_fixed(const vnl_matrix_fixed& rhs) = default; - vnl_matrix_fixed(vnl_matrix_fixed&& other) = default; - //: Copy another vnl_matrix_fixed into this. - vnl_matrix_fixed& operator=(const vnl_matrix_fixed& rhs) = default; - vnl_matrix_fixed& operator=(vnl_matrix_fixed&& rhs) = default; - ~vnl_matrix_fixed() = default; - - - //: Construct an empty num_rows*num_cols matrix - // - // The sole purpose of this constructor is to match the interface of - // vnl_matrix, so that algorithms can template over the matrix type - // itself. It is illegal to call this constructor without - // n==num_rows and m==num_cols. - vnl_matrix_fixed( unsigned VXL_USED_IN_DEBUG(n), unsigned VXL_USED_IN_DEBUG(m) ) - { - assert( n == num_rows && m == num_cols ); - } - - //: Construct an m*n matrix and fill with value - explicit vnl_matrix_fixed(T value) - { - T* p = data_[0]; - unsigned int n = num_rows * num_cols; - while (n--) - *p++ = value; - } - - //: Construct an m*n Matrix and copy data into it row-wise. - explicit vnl_matrix_fixed(const T* datablck) - { - std::memcpy(data_[0], datablck, num_rows*num_cols*sizeof(T)); - } - - //: Construct an m*n Matrix and copy rhs into it. - // Abort if rhs is not the same size. - vnl_matrix_fixed(const vnl_matrix& rhs) - { - assert(rhs.rows() == num_rows && rhs.columns() == num_cols); - std::memcpy(data_[0], rhs.data_block(), num_rows*num_cols*sizeof(T)); - } - - - //: Set all elements to value v - // Complexity $O(r.c)$ - vnl_matrix_fixed& operator= (T const&v); - - //: Copy a vnl_matrix into this. - // Abort if rhs is not the same size. - vnl_matrix_fixed& operator=(const vnl_matrix& rhs); - -// Basic 2D-Array functionality------------------------------------------- - - //: Return the total number of elements stored by the matrix. - // This equals rows() * cols() - inline unsigned int size() const { return num_rows*num_cols; } - - //: Return the number of rows. - inline unsigned int rows() const { return num_rows; } - - //: Return the number of columns. - // A synonym for columns(). - inline unsigned int cols() const { return num_cols; } - - //: Return the number of columns. - // A synonym for cols(). - inline unsigned int columns() const { return num_cols; } - - //: set element - inline void put (unsigned r, unsigned c, T const& v) - { -#if VNL_CONFIG_CHECK_BOUNDS - if (r >= num_rows) // If invalid size specified - vnl_error_matrix_row_index("put", r); // Raise exception - if (c >= num_cols) // If invalid size specified - vnl_error_matrix_col_index("put", c); // Raise exception -#endif - this->data_[r][c] = v; - } - - //: get element - inline T get (unsigned r, unsigned c) const - { -#if VNL_CONFIG_CHECK_BOUNDS - if (r >= num_rows) // If invalid size specified - vnl_error_matrix_row_index("get", r); // Raise exception - if (c >= num_cols) // If invalid size specified - vnl_error_matrix_col_index("get", c); // Raise exception -#endif - return this->data_[r][c]; - } - - //: set element, and return *this - vnl_matrix_fixed& set (unsigned r, unsigned c, T const& v) { (*this)(r,c) = v; return *this; } - - //: return pointer to given row - // No boundary checking here. - T * operator[] (unsigned r) { return data_[r]; } - - //: return pointer to given row - // No boundary checking here. - T const * operator[] (unsigned r) const { return data_[r]; } - - //: Access an element for reading or writing - // There are assert style boundary checks - #define NDEBUG to turn them off. - T & operator() (unsigned r, unsigned c); - - //: Access an element for reading - // There are assert style boundary checks - #define NDEBUG to turn them off. - T const & operator() (unsigned r, unsigned c) const; - - // ----------------------- Filling and copying ----------------------- - - //: Sets all elements of matrix to specified value, and returns "*this". - // Complexity $O(r.c)$ - // Returning "*this" allows "chaining" two or more operations: - // e.g., to set a matrix to a column-normalized all-elements-equal matrix, say - // \code - // M.fill(1).normalize_columns(); - // \endcode - // Returning "*this" also allows passing such a matrix as argument - // to a function f, without having to name the constructed matrix: - // \code - // f(vnl_matrix_fixed(1.0).normalize_columns()); - // \endcode - vnl_matrix_fixed& fill(T); - - //: Sets all diagonal elements of matrix to specified value; returns "*this". - // Complexity $O(\min(r,c))$ - // Returning "*this" allows "chaining" two or more operations: - // e.g., to set a 3x3 matrix to [5 0 0][0 10 0][0 0 15], just say - // \code - // M.fill_diagonal(5).scale_row(1,2).scale_column(2,3); - // \endcode - // Returning "*this" also allows passing a diagonal-filled matrix as argument - // to a function f, without having to name the constructed matrix: - // \code - // f(vnl_matrix_fixed().fill_diagonal(5)); - // \endcode - vnl_matrix_fixed& fill_diagonal(T); - - //: Sets the diagonal elements of this matrix to the specified list of values. - // Returning "*this" allows "chaining" two or more operations: see the - // reasoning (and the examples) in the documentation for method - // fill_diagonal(). - vnl_matrix_fixed& set_diagonal(vnl_vector const&); - - //: Fills (laminates) this matrix with the given data, then returns it. - // We assume that the argument points to a contiguous rows*cols array, stored rowwise. - // No bounds checking on the array. - // Returning "*this" allows "chaining" two or more operations: - // e.g., to fill a square matrix column-wise, fill it rowwise then transpose: - // \code - // M.copy_in(array).inplace_transpose(); - // \endcode - // Returning "*this" also allows passing a filled-in matrix as argument - // to a function f, without having to name the constructed matrix: - // \code - // f(vnl_matrix_fixed().copy_in(array)); - // \endcode - vnl_matrix_fixed& copy_in(T const *); - - //: Fills (laminates) this matrix with the given data, then returns it. - // A synonym for copy_in() - vnl_matrix_fixed& set(T const *d) { return copy_in(d); } - - //: Fills the given array with this matrix. - // We assume that the argument points to a contiguous rows*cols array, stored rowwise. - // No bounds checking on the array. - void copy_out(T *) const; - - //: Transposes this matrix efficiently, if it is square, and returns it. - // Returning "*this" allows "chaining" two or more operations: - // e.g., to fill a square matrix column-wise, fill it rowwise then transpose: - // \code - // M.copy_in(array).inplace_transpose(); - // \endcode - vnl_matrix_fixed& inplace_transpose(); - - // ----------------------- Arithmetic -------------------------------- - // note that these functions should not pass scalar as a const&. - // Look what would happen to A /= A(0,0). - - //: Add \a s to each element of lhs matrix in situ - vnl_matrix_fixed& operator+= (T s) - { - self::add( data_block(), s, data_block() ); return *this; - } - - //: Subtract \a s from each element of lhs matrix in situ - vnl_matrix_fixed& operator-= (T s) - { - self::sub( data_block(), s, data_block() ); return *this; - } - - //: - vnl_matrix_fixed& operator*= (T s) - { - self::mul( data_block(), s, data_block() ); return *this; - } - - //: - vnl_matrix_fixed& operator/= (T s) - { - self::div( data_block(), s, data_block() ); return *this; - } - - //: - vnl_matrix_fixed& operator+= (vnl_matrix_fixed const& m) - { - self::add( data_block(), m.data_block(), data_block() ); return *this; - } - - //: - vnl_matrix_fixed& operator+= (vnl_matrix const& m) - { - assert( m.rows() == rows() && m.cols() == cols() ); - self::add( data_block(), m.data_block(), data_block() ); return *this; - } - - //: - vnl_matrix_fixed& operator-= (vnl_matrix_fixed const& m) - { - self::sub( data_block(), m.data_block(), data_block() ); return *this; - } - - //: - vnl_matrix_fixed& operator-= (vnl_matrix const& m) - { - assert( m.rows() == rows() && m.cols() == cols() ); - self::sub( data_block(), m.data_block(), data_block() ); - return *this; - } - - //: Negate all elements of matrix - vnl_matrix_fixed operator- () const - { - vnl_matrix_fixed r; - self::sub( T(0), data_block(), r.data_block() ); - return r; - } - - //: - vnl_matrix_fixed& operator*= (vnl_matrix_fixed const& s) - { - vnl_matrix_fixed out; - for (unsigned i = 0; i < num_rows; ++i) - for (unsigned j = 0; j < num_cols; ++j) - { - T accum = this->data_[i][0] * s(0,j); - for (unsigned k = 1; k < num_cols; ++k) - accum += this->data_[i][k] * s(k,j); - out(i,j) = accum; - } - return *this = out; - } - - ////--------------------------- Additions ---------------------------- - - //: Make a new matrix by applying function to each element. - vnl_matrix_fixed apply(T (*f)(T)) const; - - //: Make a new matrix by applying function to each element. - vnl_matrix_fixed apply(T (*f)(T const&)) const; - - //: Make a vector by applying a function across rows. - vnl_vector_fixed apply_rowwise(T (*f)(vnl_vector_fixed const&)) const; - - //: Make a vector by applying a function across columns. - vnl_vector_fixed apply_columnwise(T (*f)(vnl_vector_fixed const&)) const; - - //: Return transpose - vnl_matrix_fixed transpose() const; - - //: Return conjugate transpose - vnl_matrix_fixed conjugate_transpose() const; - - //: Set values of this matrix to those of M, starting at [top,left] - vnl_matrix_fixed& update(vnl_matrix const&, unsigned top=0, unsigned left=0); - - //: Set the elements of the i'th column to v[i] (No bounds checking) - vnl_matrix_fixed& set_column(unsigned i, T const * v); - - //: Set the elements of the i'th column to value, then return *this. - vnl_matrix_fixed& set_column(unsigned i, T value ); - - //: Set j-th column to v, then return *this. - vnl_matrix_fixed& set_column(unsigned j, vnl_vector const& v); - - //: Set j-th column to v, then return *this. - vnl_matrix_fixed& set_column(unsigned j, vnl_vector_fixed const& v); - - //: Set columns to those in M, starting at starting_column, then return *this. - vnl_matrix_fixed& set_columns(unsigned starting_column, vnl_matrix const& M); - - //: Set the elements of the i'th row to v[i] (No bounds checking) - vnl_matrix_fixed& set_row (unsigned i, T const * v); - - //: Set the elements of the i'th row to value, then return *this. - vnl_matrix_fixed& set_row (unsigned i, T value ); - - //: Set the i-th row, then return *this. - vnl_matrix_fixed& set_row (unsigned i, vnl_vector const&); - - //: Set the i-th row, then return *this. - vnl_matrix_fixed& set_row (unsigned i, vnl_vector_fixed const&); - - //: Extract a sub-matrix of size r x c, starting at (top,left) - // Thus it contains elements [top,top+r-1][left,left+c-1] - vnl_matrix extract (unsigned r, unsigned c, - unsigned top=0, unsigned left=0) const; - - //: Extract a sub-matrix starting at (top,left) - // - // The output is stored in \a sub_matrix, and it should have the - // required size on entry. Thus the result will contain elements - // [top,top+sub_matrix.rows()-1][left,left+sub_matrix.cols()-1] - void extract ( vnl_matrix& sub_matrix, - unsigned top=0, unsigned left=0) const; - - //: Get a vector equal to the given row - vnl_vector_fixed get_row (unsigned row) const; - - //: Get a vector equal to the given column - vnl_vector_fixed get_column(unsigned col) const; - - //: Get a matrix composed of rows from the indices specified in the supplied vector. - vnl_matrix get_rows(vnl_vector i) const; - - //: Get a matrix composed of columns from the indices specified in the supplied vector. - vnl_matrix get_columns(vnl_vector i) const; - - //: Get n rows beginning at rowstart - vnl_matrix get_n_rows (unsigned rowstart, unsigned n) const; - - //: Get n columns beginning at colstart - vnl_matrix get_n_columns(unsigned colstart, unsigned n) const; - - //: Return a vector with the content of the (main) diagonal - vnl_vector get_diagonal() const; - - //: Flatten row-major (C-style) - vnl_vector_fixed flatten_row_major() const; - - //: Flatten column-major (Fortran-style) - vnl_vector_fixed flatten_column_major() const; - - // ==== mutators ==== - - //: Sets this matrix to an identity matrix, then returns "*this". - // Returning "*this" allows e.g. passing an identity matrix as argument to - // a function f, without having to name the constructed matrix: - // \code - // f(vnl_matrix_fixed().set_identity()); - // \endcode - // Returning "*this" also allows "chaining" two or more operations: - // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say - // \code - // M.set_identity().scale_row(0,3).scale_column(1,2); - // \endcode - // If the matrix is not square, anyhow set main diagonal to 1, the rest to 0. - vnl_matrix_fixed& set_identity(); - - //: Reverses the order of rows, and returns "*this". - // Returning "*this" allows "chaining" two or more operations: - // e.g., to flip both up-down and left-right, one could just say - // \code - // M.flipud().fliplr(); - // \endcode - vnl_matrix_fixed& flipud(); - - //: Reverses the order of columns, and returns "*this". - // Returning "*this" allows "chaining" two or more operations: - // e.g., to flip both up-down and left-right, one could just say - // \code - // M.flipud().fliplr(); - // \endcode - vnl_matrix_fixed& fliplr(); - - //: Normalizes each row so it is a unit vector, and returns "*this". - // Zero rows are not modified - // Returning "*this" allows "chaining" two or more operations: - // e.g., to set a matrix to a row-normalized all-elements-equal matrix, say - // \code - // M.fill(1).normalize_rows(); - // \endcode - // Returning "*this" also allows passing such a matrix as argument - // to a function f, without having to name the constructed matrix: - // \code - // f(vnl_matrix_fixed(1.0).normalize_rows()); - // \endcode - vnl_matrix_fixed& normalize_rows(); - - //: Normalizes each column so it is a unit vector, and returns "*this". - // Zero columns are not modified - // Returning "*this" allows "chaining" two or more operations: - // e.g., to set a matrix to a column-normalized all-elements-equal matrix, say - // \code - // M.fill(1).normalize_columns(); - // \endcode - // Returning "*this" also allows passing such a matrix as argument - // to a function f, without having to name the constructed matrix: - // \code - // f(vnl_matrix_fixed(1.0).normalize_columns()); - // \endcode - vnl_matrix_fixed& normalize_columns(); - - //: Scales elements in given row by a factor T, and returns "*this". - // Returning "*this" allows "chaining" two or more operations: - // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say - // \code - // M.set_identity().scale_row(0,3).scale_column(1,2); - // \endcode - vnl_matrix_fixed& scale_row (unsigned row, T value); - - //: Scales elements in given column by a factor T, and returns "*this". - // Returning "*this" allows "chaining" two or more operations: - // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say - // \code - // M.set_identity().scale_row(0,3).scale_column(1,2); - // \endcode - vnl_matrix_fixed& scale_column(unsigned col, T value); - - //: Swap this matrix with that matrix - void swap(vnl_matrix_fixed & that); - - //: Type def for norms. - typedef typename vnl_c_vector::abs_t abs_t; - - //: Return sum of absolute values of elements - abs_t array_one_norm() const { return vnl_c_vector::one_norm(begin(), size()); } - - //: Return square root of sum of squared absolute element values - abs_t array_two_norm() const { return vnl_c_vector::two_norm(begin(), size()); } - - //: Return largest absolute element value - abs_t array_inf_norm() const { return vnl_c_vector::inf_norm(begin(), size()); } - - //: Return sum of absolute values of elements - abs_t absolute_value_sum() const { return array_one_norm(); } - - //: Return largest absolute value - abs_t absolute_value_max() const { return array_inf_norm(); } - - // $ || M ||_1 := \max_j \sum_i | M_{ij} | $ - abs_t operator_one_norm() const; - - // $ || M ||_\inf := \max_i \sum_j | M_{ij} | $ - abs_t operator_inf_norm() const; - - //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements) - abs_t frobenius_norm() const { return vnl_c_vector::two_norm(begin(), size()); } - - //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements) - abs_t fro_norm() const { return frobenius_norm(); } - - //: Return RMS of all elements - abs_t rms() const { return vnl_c_vector::rms_norm(begin(), size()); } - - //: Return minimum value of elements - T min_value() const { return vnl_c_vector::min_value(begin(), size()); } - - //: Return maximum value of elements - T max_value() const { return vnl_c_vector::max_value(begin(), size()); } - - //: Return location of minimum value of elements - unsigned arg_min() const { return vnl_c_vector::arg_min(begin(), size()); } - - //: Return location of maximum value of elements - unsigned arg_max() const { return vnl_c_vector::arg_max(begin(), size()); } - - //: Return mean of all matrix elements - T mean() const { return vnl_c_vector::mean(begin(), size()); } - - // predicates - - //: Return true iff the size is zero. - bool empty() const { return num_rows==0 && num_cols==0; } - - //: Return true if all elements equal to identity. - bool is_identity() const; - - //: Return true if all elements equal to identity, within given tolerance - bool is_identity(double tol) const; - - //: Return true if all elements equal to zero. - bool is_zero() const; - - //: Return true if all elements equal to zero, within given tolerance - bool is_zero(double tol) const; - - //: Return true if all elements of both matrices are equal, within given tolerance - bool is_equal(vnl_matrix_fixed const& rhs, double tol) const; - - //: Return true if finite - bool is_finite() const; - - //: Return true if matrix contains NaNs - bool has_nans() const; - - //: abort if size is not as expected - // This function does or tests nothing if NDEBUG is defined - void assert_size(unsigned VXL_USED_IN_DEBUG(nr_rows), unsigned VXL_USED_IN_DEBUG(nr_cols) ) const - { -#ifndef NDEBUG - assert_size_internal(nr_rows, nr_cols); -#endif - } - - //: abort if matrix contains any INFs or NANs. - // This function does or tests nothing if NDEBUG is defined - void assert_finite() const - { -#ifndef NDEBUG - assert_finite_internal(); -#endif - } - - ////----------------------- Input/Output ---------------------------- - - // : Read a vnl_matrix from an ascii std::istream, automatically determining file size if the input matrix has zero size. - bool read_ascii(std::istream& s); - - //-------------------------------------------------------------------------------- - - //: Access the contiguous block storing the elements in the matrix row-wise. O(1). - // 1d array, row-major order. - T const* data_block() const; - - //: Access the contiguous block storing the elements in the matrix row-wise. O(1). - // 1d array, row-major order. - T * data_block(); - - - //---------------------------------------------------------------------- - // Conversion to vnl_matrix_ref. - - // The const version of as_ref should return a const vnl_matrix_ref - // so that the vnl_matrix_ref::non_const() cannot be used on - // it. This prevents a const vnl_matrix_fixed from being cast into a - // non-const vnl_matrix reference, giving a slight increase in type safety. - - //: Explicit conversion to a vnl_matrix_ref. - // This is a cheap conversion for those functions that have an interface - // for vnl_matrix but not for vnl_matrix_fixed. There is also a - // conversion operator that should work most of the time. - // \sa vnl_matrix_ref::non_const - inline vnl_matrix_ref as_ref() { return vnl_matrix_ref( num_rows, num_cols, data_block() ); } - - //: Explicit conversion to a vnl_matrix_ref. - // This is a cheap conversion for those functions that have an interface - // for vnl_matrix but not for vnl_matrix_fixed. There is also a - // conversion operator that should work most of the time. - // \sa vnl_matrix_ref::non_const - inline const vnl_matrix_ref as_ref() const { return vnl_matrix_ref( num_rows, num_cols, const_cast(data_block()) ); } - - //: Cheap conversion to vnl_matrix_ref - // Sometimes, such as with templated functions, the compiler cannot - // use this user-defined conversion. For those cases, use the - // explicit as_ref() method instead. - inline operator const vnl_matrix_ref() const { return vnl_matrix_ref( num_rows, num_cols, const_cast(data_block()) ); } - - //: Convert to a vnl_matrix. - inline const vnl_matrix as_matrix() const { return vnl_matrix(const_cast(data_block()),num_rows,num_cols); } - - //---------------------------------------------------------------------- - - typedef T element_type; - - //: Iterators - typedef T *iterator; - //: Iterator pointing to start of data - inline iterator begin() { return data_[0]; } - //: Iterator pointing to element beyond end of data - inline iterator end() { return begin() + size(); } - - //: Const iterators - typedef T const *const_iterator; - //: Iterator pointing to start of data - inline const_iterator begin() const { return data_[0]; } - //: Iterator pointing to element beyond end of data - inline const_iterator end() const { return begin() + size(); } - - //-------------------------------------------------------------------------------- - - //: Return true if *this == rhs - bool operator_eq (vnl_matrix_fixed const & rhs) const - { - return equal( this->data_block(), rhs.data_block() ); - } - - //: Equality operator - bool operator==(vnl_matrix_fixed const &that) const { return this->operator_eq(that); } - - //: Inequality operator - bool operator!=(vnl_matrix_fixed const &that) const { return !this->operator_eq(that); } - - //: Equality operator - bool operator==(vnl_matrix const &that) const { return this->operator_eq(that); } - - //: Inequality operator - bool operator!=(vnl_matrix const &that) const { return !this->operator_eq(that); } - - //: Print matrix to os in some hopefully sensible format - void print(std::ostream& os) const; - -//-------------------------------------------------------------------------------- - - - // Helper routines for arithmetic. These routines know the size from - // the template parameters. The vector-vector operations are - // element-wise. - - static void add( const T* a, const T* b, T* r ); - static void add( const T* a, T b, T* r ); - static void sub( const T* a, const T* b, T* r ); - static void sub( const T* a, T b, T* r ); - static void sub( T a, const T* b, T* r ); - static void mul( const T* a, const T* b, T* r ); - static void mul( const T* a, T b, T* r ); - static void div( const T* a, const T* b, T* r ); - static void div( const T* a, T b, T* r ); - - static bool equal( const T* a, const T* b ); - - private: - void assert_finite_internal() const; - - void assert_size_internal(unsigned, unsigned) const; -}; - -// Make the operators below inline because (1) they are small and -// (2) we then have less explicit instantiation trouble. - - -// --- Matrix-scalar ------------------------------------------------------------- - -template -inline -vnl_matrix_fixed operator+( const vnl_matrix_fixed& mat1, const vnl_matrix_fixed& mat2 ) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::add( mat1.data_block(), mat2.data_block(), r.data_block() ); - return r; -} - -template -inline -vnl_matrix_fixed operator+( const vnl_matrix_fixed& mat, T s ) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::add( mat.data_block(), s, r.data_block() ); - return r; -} - -template -inline -vnl_matrix_fixed operator+( const T& s, - const vnl_matrix_fixed& mat ) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::add( mat.data_block(), s, r.data_block() ); - return r; -} - -template -inline -vnl_matrix_fixed operator-( const vnl_matrix_fixed& mat1, const vnl_matrix_fixed& mat2 ) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::sub( mat1.data_block(), mat2.data_block(), r.data_block() ); - return r; -} - -template -inline -vnl_matrix_fixed operator-( const vnl_matrix_fixed& mat, T s ) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::sub( mat.data_block(), s, r.data_block() ); - return r; -} - -template -inline -vnl_matrix_fixed operator-( const T& s, - const vnl_matrix_fixed& mat ) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::sub( s, mat.data_block(), r.data_block() ); - return r; -} - -template -inline -vnl_matrix_fixed operator*( const vnl_matrix_fixed& mat, T s ) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::mul( mat.data_block(), s, r.data_block() ); - return r; -} - -template -inline -vnl_matrix_fixed operator*( const T& s, - const vnl_matrix_fixed& mat ) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::mul( mat.data_block(), s, r.data_block() ); - return r; -} - -template -inline -vnl_matrix_fixed operator/( const vnl_matrix_fixed& mat, T s ) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::div( mat.data_block(), s, r.data_block() ); - return r; -} - - -template -inline -vnl_matrix_fixed element_product( const vnl_matrix_fixed& mat1, - const vnl_matrix_fixed& mat2 ) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::mul( mat1.data_block(), mat2.data_block(), r.data_block() ); - return r; -} - - -template -inline -vnl_matrix_fixed element_quotient( const vnl_matrix_fixed& mat1, - const vnl_matrix_fixed& mat2) -{ - vnl_matrix_fixed r; - vnl_matrix_fixed::div( mat1.data_block(), mat2.data_block(), r.data_block() ); - return r; -} - - -// The following two functions are helper functions keep the -// matrix-matrix and matrix-vector multiplication code in one place, -// so that bug fixes, etc, can be localized. -template -inline -vnl_vector_fixed -vnl_matrix_fixed_mat_vec_mult(const vnl_matrix_fixed& a, - const vnl_vector_fixed& b) -{ - vnl_vector_fixed out; - for (unsigned i = 0; i < M; ++i) - { - T accum = a(i,0) * b(0); - for (unsigned k = 1; k < N; ++k) - accum += a(i,k) * b(k); - out(i) = accum; - } - return out; -} - -template -inline -vnl_vector_fixed -vnl_matrix_fixed_vec_mat_mult(const vnl_vector_fixed& a, - const vnl_matrix_fixed& b) -{ - vnl_vector_fixed out; - for (unsigned i = 0; i < N; ++i) - { - T accum = a(0) * b(0,i); - for (unsigned k = 1; k < M; ++k) - accum += a(k) * b(k,i); - out(i) = accum; - } - return out; -} - -// see comment above -template -inline -vnl_matrix_fixed -vnl_matrix_fixed_mat_mat_mult(const vnl_matrix_fixed& a, - const vnl_matrix_fixed& b) -{ - vnl_matrix_fixed out; - for (unsigned i = 0; i < M; ++i) - for (unsigned j = 0; j < O; ++j) - { - T accum = a(i,0) * b(0,j); - for (unsigned k = 1; k < N; ++k) - accum += a(i,k) * b(k,j); - out(i,j) = accum; - } - return out; -} - -// The version for correct compilers - -//: Multiply conformant vnl_matrix_fixed (M x N) and vector_fixed (N) -// \relatesalso vnl_vector_fixed -// \relatesalso vnl_matrix_fixed -template -inline -vnl_vector_fixed operator*(const vnl_matrix_fixed& a, const vnl_vector_fixed& b) -{ - return vnl_matrix_fixed_mat_vec_mult(a, b); -} - -//: Multiply conformant vector_fixed (M) and vnl_matrix_fixed (M x N) -// \relatesalso vnl_vector_fixed -// \relatesalso vnl_matrix_fixed -template -inline -vnl_vector_fixed operator*(const vnl_vector_fixed& a, const vnl_matrix_fixed& b) -{ - return vnl_matrix_fixed_vec_mat_mult(a, b); -} - -//: Multiply two conformant vnl_matrix_fixed (M x N) times (N x O) -// \relatesalso vnl_matrix_fixed -template -inline -vnl_matrix_fixed operator*(const vnl_matrix_fixed& a, const vnl_matrix_fixed& b) -{ - return vnl_matrix_fixed_mat_mat_mult(a, b); -} - - -// These overloads for the common case of mixing a fixed with a -// non-fixed. Because the operator* are templated, the fixed will not -// be automatically converted to a non-fixed-ref. These do it for you. - -template -inline vnl_matrix operator+( const vnl_matrix_fixed& a, const vnl_matrix& b ) -{ - return a.as_ref() + b; -} - -template -inline vnl_matrix operator+( const vnl_matrix& a, const vnl_matrix_fixed& b ) -{ - return a + b.as_ref(); -} - -template -inline vnl_matrix operator-( const vnl_matrix_fixed& a, const vnl_matrix& b ) -{ - return a.as_ref() - b; -} - -template -inline vnl_matrix operator-( const vnl_matrix& a, const vnl_matrix_fixed& b ) -{ - return a - b.as_ref(); -} - -template -inline vnl_matrix operator*( const vnl_matrix_fixed& a, const vnl_matrix& b ) -{ - return a.as_ref() * b; -} - -template -inline vnl_matrix operator*( const vnl_matrix& a, const vnl_matrix_fixed& b ) -{ - return a * b.as_ref(); -} - -template -inline vnl_vector operator*( const vnl_matrix_fixed& a, const vnl_vector& b ) -{ - return a.as_ref() * b; -} - -template -inline vnl_vector operator*( const vnl_matrix& a, const vnl_vector_fixed& b ) -{ - return a * b.as_ref(); -} - - -// --- I/O operations ------------------------------------------------------------ - -template -inline -std::ostream& operator<< (std::ostream& os, vnl_matrix_fixed const& mat) -{ - mat.print(os); - return os; -} - -template -inline -std::istream& operator>> (std::istream& is, vnl_matrix_fixed& mat) -{ - mat.read_ascii(is); - return is; -} - -//: -// \relatesalso vnl_vector_fixed -template VNL_EXPORT -vnl_matrix_fixed outer_product(vnl_vector_fixed const& a, vnl_vector_fixed const& b); - -#define VNL_MATRIX_FIXED_INSTANTIATE(T, M, N) \ -extern "please include vnl/vnl_matrix_fixed.hxx instead" - -#endif // vnl_matrix_fixed_h_ diff --git a/Patches/VXL/vnl_transpose.h b/Patches/VXL/vnl_transpose.h deleted file mode 100644 index 5108e70d..00000000 --- a/Patches/VXL/vnl_transpose.h +++ /dev/null @@ -1,77 +0,0 @@ -// This is core/vnl/vnl_transpose.h -#ifndef vnl_transpose_h_ -#define vnl_transpose_h_ -//: -// \file -// \brief Efficient matrix transpose -// \author Andrew W. Fitzgibbon, Oxford RRG -// \date 23 Dec 96 -// -// \verbatim -// Modifications -// LSB (Manchester) 19/3/01 Tidied documentation -// \endverbatim - -#include -#ifdef _MSC_VER -# include -#endif -#include -#include "vnl/vnl_export.h" - -//: Efficient matrix transpose -// vnl_transpose is an efficient way to write C = vnl_transpose(A) * B. -// The vnl_transpose class holds a reference to the original matrix -// and when involved in an operation for which it has been specialized, -// performs the operation without copying. -// -// If the operation has not been specialized, the vnl_transpose performs -// a copying conversion to a matrix, printing a message to stdout. -// At that stage, the user may choose to implement the particular operation -// or use vnl_transpose::asMatrix() to clear the warning. -// -// NOTE: This is a reference class, so should be shorter-lived than the -// matrix to which it refers. -// -// NOTE: This only works for arguments of type vnl_matrix - -class vnl_transpose -{ - const vnl_matrix& M_; - public: - - //: Make a vnl_transpose object referring to matrix M - vnl_transpose(const vnl_matrix& M): M_(M) {} - - //: Noisily convert a vnl_transpose to a matrix - operator vnl_matrix () const { - std::cerr << "vnl_transpose being converted to matrix -- help! I don't wanna go!\n"; - return M_.transpose(); - } - - //: Quietly convert a vnl_transpose to a matrix - vnl_matrix asMatrix () const { return M_.transpose(); } - - //: Return M' * O - vnl_matrix operator* (const vnl_matrix& O) { - vnl_matrix ret(M_.columns(), O.columns()); - vnl_fastops::AtB(ret, M_, O); - return ret; - } - - //: Return M' * O - vnl_vector operator* (const vnl_vector& O) { - vnl_vector ret(M_.columns()); - vnl_fastops::AtB(ret, M_, O); - return ret; - } - - //: Return A * B' - friend vnl_matrix operator* (const vnl_matrix& A, const vnl_transpose& B) { - vnl_matrix ret(A.rows(), B.M_.rows()); - vnl_fastops::ABt(ret, A, B.M_); - return ret; - } -}; - -#endif // vnl_transpose_h_ From a411b4e63602a4b2e3b0cdfb9d629e892b67cedc Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Mon, 22 Jul 2019 16:02:26 -0400 Subject: [PATCH 19/22] Revert "Modify patch" This reverts commit 814e90a840fac266f0b493c4e2e9c74a8e0bfbd2. --- Patches/VXL/FindFFMPEG.cmake | 87 ++++ Patches/VXL/Patch.cmake | 4 +- Patches/VXL/vidl_ffmpeg_ostream_v56.hxx | 606 ------------------------ 3 files changed, 89 insertions(+), 608 deletions(-) create mode 100644 Patches/VXL/FindFFMPEG.cmake delete mode 100644 Patches/VXL/vidl_ffmpeg_ostream_v56.hxx diff --git a/Patches/VXL/FindFFMPEG.cmake b/Patches/VXL/FindFFMPEG.cmake new file mode 100644 index 00000000..c6c8eb7e --- /dev/null +++ b/Patches/VXL/FindFFMPEG.cmake @@ -0,0 +1,87 @@ +# Find the FFmpeg library +# +# Sets +# FFMPEG_FOUND. If false, don't try to use ffmpeg +# FFMPEG_FOUND_SEVERAL. If true, there are several directories with headers (not only ../ffmpeg/) +# FFMPEG_INCLUDE_DIR +# FFMPEG_LIBRARIES + +set( FFMPEG_FOUND "NO" ) + +find_path( FFMPEG_INCLUDE1_DIR ffmpeg/avcodec.h + /usr/include + /usr/local/include +) +find_path( FFMPEG_INCLUDE2_DIR libavcodec/avcodec.h + /usr/include + /usr/local/include +) +if( FFMPEG_INCLUDE1_DIR ) + set( FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE1_DIR} ) +endif() + +if( FFMPEG_INCLUDE2_DIR ) + set( FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE2_DIR} ) +endif() + +if( FFMPEG_INCLUDE_DIR AND FFMPEG_INCLUDE2_DIR ) + set( FFMPEG_FOUND_SEVERAL "YES" ) +else() + set( FFMPEG_FOUND_SEVERAL "NO" ) +endif() + +find_program( FFMPEG_CONFIG ffmpeg-config + /usr/bin + /usr/local/bin + ${HOME}/bin +) + +if( FFMPEG_CONFIG ) + exec_program( ${FFMPEG_CONFIG} ARGS "--libs avformat" OUTPUT_VARIABLE FFMPEG_LIBS ) + set( FFMPEG_FOUND "YES" ) + set( FFMPEG_LIBRARIES "${FFMPEG_LIBS}" ) + +else() + + find_library( FFMPEG_avcodec_LIBRARY avcodec + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + find_library( FFMPEG_avformat_LIBRARY avformat + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + find_library( FFMPEG_avutil_LIBRARY avutil + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + find_library( FFMPEG_swscale_LIBRARY swscale + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + if( FFMPEG_avcodec_LIBRARY ) + if( FFMPEG_avformat_LIBRARY ) + set( FFMPEG_FOUND "YES" ) + set( FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} ${FFMPEG_avcodec_LIBRARY} ) + if( FFMPEG_avutil_LIBRARY ) + set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_avutil_LIBRARY} ) + endif() + if( FFMPEG_swscale_LIBRARY ) + set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_swscale_LIBRARY} ) + endif() + endif() + endif() + +endif() diff --git a/Patches/VXL/Patch.cmake b/Patches/VXL/Patch.cmake index 1e4b7c8e..1a4005a5 100644 --- a/Patches/VXL/Patch.cmake +++ b/Patches/VXL/Patch.cmake @@ -5,6 +5,6 @@ message("Patching VXL in ${VXL_source}") -file(COPY ${VXL_patch}//vidl_ffmpeg_ostream_v56.hxx - DESTINATION ${VXL_source}/core/vidl/ +file(COPY ${VXL_patch}/FindFFMPEG.cmake + DESTINATION ${VXL_source}/config/cmake/Modules/NewCMake/ ) diff --git a/Patches/VXL/vidl_ffmpeg_ostream_v56.hxx b/Patches/VXL/vidl_ffmpeg_ostream_v56.hxx deleted file mode 100644 index 1e4d4686..00000000 --- a/Patches/VXL/vidl_ffmpeg_ostream_v56.hxx +++ /dev/null @@ -1,606 +0,0 @@ -// This is core/vidl/vidl_ffmpeg_ostream_v56.hxx -#ifndef vidl_ffmpeg_ostream_v56_hxx_ -#define vidl_ffmpeg_ostream_v56_hxx_ -#pragma once - -#include -#include -#include "vidl_ffmpeg_ostream.h" -//: -// \file -// \author Johan Andruejol -// \author Gehua Yang -// \author Matt Leotta -// \author Amitha Perera -// \author David Law -// \date 6 April 2015 -// -// Update implementation based on FFMPEG release version 2.8.4 -// -//----------------------------------------------------------------------------- - -#include "vidl_ffmpeg_init.h" -#include "vidl_ffmpeg_convert.h" -#include "vidl_ffmpeg_pixel_format.h" -#include "vidl_frame.h" -#include "vidl_convert.h" -#ifdef _MSC_VER -# include -#endif -#include -#include - -extern "C" { -#if FFMPEG_IN_SEVERAL_DIRECTORIES -#include -#include -#include -#include - -#else -#include -#include -#endif -} - -//----------------------------------------------------------------------------- - - -struct vidl_ffmpeg_ostream::pimpl -{ - pimpl() - : fmt_cxt_( nullptr ), - file_opened_( false ), - codec_opened_( false ), - cur_frame_( 0 ), - video_rc_eq_( nullptr ) - { } - - AVFormatContext* fmt_cxt_; - bool file_opened_; - bool codec_opened_; - unsigned int cur_frame_; - char* video_rc_eq_; -}; - - -//----------------------------------------------------------------------------- - - -//: Constructor -vidl_ffmpeg_ostream:: -vidl_ffmpeg_ostream() - : os_( new vidl_ffmpeg_ostream::pimpl ) -{ - vidl_ffmpeg_init(); -} - - -//: Destructor -vidl_ffmpeg_ostream:: -~vidl_ffmpeg_ostream() -{ - close(); - delete os_; -} - - -//: Constructor - opens a stream -vidl_ffmpeg_ostream:: -vidl_ffmpeg_ostream(const std::string & filename, - const vidl_ffmpeg_ostream_params & params) - : os_( new vidl_ffmpeg_ostream::pimpl ), - filename_(std::move(filename)), params_(std::move(params)) -{ - vidl_ffmpeg_init(); -} - - -//: Open the stream -bool -vidl_ffmpeg_ostream:: -open() -{ - // Close any open files - close(); - - os_->fmt_cxt_ = avformat_alloc_context(); - - AVOutputFormat* file_oformat = nullptr; - if ( params_.file_format_ == vidl_ffmpeg_ostream_params::GUESS ) { - file_oformat = av_guess_format(nullptr, filename_.c_str(), nullptr); - if (!file_oformat) { - std::cerr << "ffmpeg: Unable for find a suitable output format for " - << filename_ << '\n'; - close(); - return false; - } - } - else { - close(); - return false; - } - - os_->fmt_cxt_->oformat = file_oformat; - os_->fmt_cxt_->nb_streams = 0; - - // Create stream - AVStream* st = avformat_new_stream( os_->fmt_cxt_, nullptr ); - if ( !st ) { - std::cerr << "ffmpeg: could not alloc stream\n"; - close(); - return false; - } - - //os_->fmt_cxt_->nb_streams = 1; - - AVCodecContext *video_enc = st->codec; - - if (std::strcmp(file_oformat->name, "mp4") != 0 || - std::strcmp(file_oformat->name, "mov") != 0 || - std::strcmp(file_oformat->name, "3gp") != 0 ) - video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER; - - video_enc->codec_type = AVMEDIA_TYPE_VIDEO; - - switch ( params_.encoder_ ) - { - case vidl_ffmpeg_ostream_params::DEFAULT: - video_enc->codec_id = file_oformat->video_codec; - break; - case vidl_ffmpeg_ostream_params::MPEG4: - video_enc->codec_id = AV_CODEC_ID_MPEG4; - break; - case vidl_ffmpeg_ostream_params::MPEG2VIDEO: - video_enc->codec_id = AV_CODEC_ID_MPEG2VIDEO; - break; - case vidl_ffmpeg_ostream_params::MSMPEG4V2: - video_enc->codec_id = AV_CODEC_ID_MSMPEG4V2; - break; - case vidl_ffmpeg_ostream_params::RAWVIDEO: - video_enc->codec_id = AV_CODEC_ID_RAWVIDEO; - break; - case vidl_ffmpeg_ostream_params::LJPEG: - video_enc->codec_id = AV_CODEC_ID_LJPEG; - break; - case vidl_ffmpeg_ostream_params::HUFFYUV: - video_enc->codec_id = AV_CODEC_ID_HUFFYUV; - break; - case vidl_ffmpeg_ostream_params::DVVIDEO: - video_enc->codec_id = AV_CODEC_ID_DVVIDEO; - break; - default: - std::cout << "ffmpeg: Unknown encoder type\n"; - return false; - } - - AVCodec* codec = avcodec_find_encoder( video_enc->codec_id ); - if ( !codec ) - { - std::cerr << "ffmpeg_writer:: couldn't find encoder for " << video_enc->codec_id << '\n'; - return false; - } - - video_enc->bit_rate = params_.bit_rate_ * 1000; - video_enc->bit_rate_tolerance = params_.video_bit_rate_tolerance_; - video_enc->time_base.num = 1000; - video_enc->time_base.den = int(params_.frame_rate_*1000); - - if ( codec && codec->supported_framerates ) - { - AVRational const* p = codec->supported_framerates; - AVRational req = { video_enc->time_base.den, video_enc->time_base.num }; - AVRational const* best = nullptr; - AVRational best_error = { INT_MAX, 1 }; - for (; p->den!=0; p++) - { - AVRational error = av_sub_q(req, *p); - if ( error.num < 0 ) error.num *= -1; - if ( av_cmp_q( error, best_error ) < 0 ) - { - best_error= error; - best= p; - } - } - video_enc->time_base.den= best->num; - video_enc->time_base.num= best->den; - } - - video_enc->width = params_.ni_; - video_enc->height = params_.nj_; - video_enc->sample_aspect_ratio = av_d2q(params_.frame_aspect_ratio_*params_.ni_/params_.nj_, 255); - - // Our source is packed RGB. Use that if possible. - video_enc->pix_fmt = AV_PIX_FMT_RGB24; - if ( codec && codec->pix_fmts ) - { - const enum AVPixelFormat* p= codec->pix_fmts; - for ( ; *p != -1; p++ ) - { - if ( *p == video_enc->pix_fmt ) - break; - } - if ( *p == -1 ) - video_enc->pix_fmt = codec->pix_fmts[0]; - } - else if ( codec && ( codec->id == AV_CODEC_ID_RAWVIDEO || - codec->id == AV_CODEC_ID_HUFFYUV ) ) - { - // these formats only support the YUV input image formats - video_enc->pix_fmt = AV_PIX_FMT_YUV420P; - } - - if (!params_.intra_only_) - video_enc->gop_size = params_.gop_size_; - else - video_enc->gop_size = 0; - if (params_.video_qscale_ || params_.same_quality_) - { - video_enc->flags |= CODEC_FLAG_QSCALE; - video_enc->global_quality = FF_QP2LAMBDA * params_.video_qscale_; - } - // if (bitexact) - // video_enc->flags |= CODEC_FLAG_BITEXACT; - - video_enc->mb_decision = params_.mb_decision_; - video_enc->mb_cmp = params_.mb_cmp_; - video_enc->ildct_cmp = params_.ildct_cmp_; - video_enc->me_sub_cmp = params_.sub_cmp_; - video_enc->me_cmp = params_.cmp_; - video_enc->me_pre_cmp = params_.pre_cmp_; - video_enc->pre_me = params_.pre_me_; - video_enc->lumi_masking = params_.lumi_mask_; - video_enc->dark_masking = params_.dark_mask_; - video_enc->spatial_cplx_masking = params_.scplx_mask_; - video_enc->temporal_cplx_masking = params_.tcplx_mask_; - video_enc->p_masking = params_.p_mask_; - // This parameter is no longer supported - //video_enc->quantizer_noise_shaping= params_.qns_; - - if (params_.use_umv_) - { - // This flag is no longer supported - std::cerr << "WARNING: global parameter 'use_umv_' no longer support by FFMPEG" << std::endl; - //video_enc->flags |= CODEC_FLAG_H263P_UMV; - } - if (params_.use_ss_) - { - // This flag is no longer supported - std::cerr << "WARNING: global parameter 'use_ss_' no longer support by FFMPEG" << std::endl; - //video_enc->flags |= CODEC_FLAG_H263P_SLICE_STRUCT; - } - if (params_.use_aiv_) - { - // This flag is no longer supported - std::cerr << "WARNING: global parameter 'use_aiv_' no longer support by FFMPEG" << std::endl; - //video_enc->flags |= CODEC_FLAG_H263P_AIV; - } - if (params_.use_4mv_) - { - video_enc->flags |= CODEC_FLAG_4MV; - } - if (params_.use_obmc_) - { - // This flag is no longer supported - std::cerr << "WARNING: global parameter 'use_obmc_' no longer support by FFMPEG" << std::endl; - //video_enc->flags |= CODEC_FLAG_OBMC; - } - if (params_.use_loop_) - { - video_enc->flags |= CODEC_FLAG_LOOP_FILTER; - } - - if (params_.use_part_) - { - // This flag is no longer supported - std::cerr << "WARNING: global parameter 'use_part_' no longer support by FFMPEG" << std::endl; - //video_enc->flags |= CODEC_FLAG_PART; - } - if (params_.use_alt_scan_) - { - // This flag is no longer supported - std::cerr << "WARNING: global parameter 'use_alt_scan_' no longer support by FFMPEG" << std::endl; - //video_enc->flags |= CODEC_FLAG_ALT_SCAN; - } - if (params_.use_scan_offset_) - { - // This flag is no longer supported - std::cerr << "WARNING: global parameter 'use_scan_offset_' no longer support by FFMPEG" << std::endl; - //video_enc->flags |= CODEC_FLAG_SVCD_SCAN_OFFSET; - } - if (params_.closed_gop_) - { - video_enc->flags |= CODEC_FLAG_CLOSED_GOP; - } - if (params_.use_qpel_) - { - video_enc->flags |= CODEC_FLAG_QPEL; - } - //if (params_.use_qprd_) - //{ - // video_enc->flags |= CODEC_FLAG_QP_RD; - //} - //if (params_.use_cbprd_) - //{ - // video_enc->flags |= CODEC_FLAG_CBP_RD; - //} - if (params_.b_frames_) - { - video_enc->max_b_frames = params_.b_frames_; - video_enc->b_frame_strategy = 0; - video_enc->b_quant_factor = 2.0; - } - if (params_.do_interlace_dct_) - { - video_enc->flags |= CODEC_FLAG_INTERLACED_DCT; - } - if (params_.do_interlace_me_) - { - video_enc->flags |= CODEC_FLAG_INTERLACED_ME; - } - video_enc->qmin = params_.video_qmin_; - video_enc->qmax = params_.video_qmax_; - av_opt_set_int(video_enc, "lmin", params_.video_lmin_, AV_OPT_SEARCH_CHILDREN); - av_opt_set_int(video_enc, "lmax", params_.video_lmax_, AV_OPT_SEARCH_CHILDREN); - video_enc->max_qdiff = params_.video_qdiff_; - video_enc->qblur = params_.video_qblur_; - video_enc->qcompress = params_.video_qcomp_; - - // delete when the stream is closed - os_->video_rc_eq_ = new char[params_.video_rc_eq_.length() + 1]; - av_opt_set(video_enc, "video_rc_eq_", params_.video_rc_eq_.c_str(), AV_OPT_SEARCH_CHILDREN); - - video_enc->debug = params_.debug_; - video_enc->debug_mv = params_.debug_mv_; - video_enc->thread_count = 1; - - video_enc->rc_max_rate = params_.video_rc_max_rate_; - video_enc->rc_min_rate = params_.video_rc_min_rate_; - av_opt_set_double(video_enc, "rc_buffer_aggressivity", params_.video_rc_buffer_aggressivity_, AV_OPT_SEARCH_CHILDREN); - av_opt_set_double(video_enc, "rc_initial_cplx", params_.video_rc_initial_cplx_, AV_OPT_SEARCH_CHILDREN); - video_enc->i_quant_factor = params_.video_i_qfactor_; - video_enc->b_quant_factor = params_.video_b_qfactor_; - video_enc->i_quant_offset = params_.video_i_qoffset_; - video_enc->b_quant_offset = params_.video_b_qoffset_; - //DEPRECATED https://www.ffmpeg.org/doxygen/3.1/structAVCodecContext.html video_enc->intra_quant_bias = params_.video_intra_quant_bias_; - //DEPRECATED https://www.ffmpeg.org/doxygen/3.1/structAVCodecContext.html video_enc->inter_quant_bias = params_.video_inter_quant_bias_; - video_enc->dct_algo = params_.dct_algo_; - video_enc->idct_algo = params_.idct_algo_; - video_enc->intra_dc_precision = params_.intra_dc_precision_ - 8; - video_enc->strict_std_compliance = params_.strict_; - av_opt_set_double(video_enc, "error_rate", params_.error_rate_, AV_OPT_SEARCH_CHILDREN); - video_enc->noise_reduction = params_.noise_reduction_; - video_enc->scenechange_threshold = params_.sc_threshold_; - video_enc->me_range = params_.me_range_; - video_enc->coder_type = params_.coder_; - video_enc->context_model = params_.context_; - video_enc->prediction_method = params_.predictor_; - - if (params_.do_psnr_) - video_enc->flags|= CODEC_FLAG_PSNR; - - //DEPRECATED: This option does nothing "https://www.ffmpeg.org/doxygen/3.1/structAVCodecContext.html#aa71b3450f1a508330e907db117ae410e" video_enc->me_method = params_.me_method_; - - // two pass mode - if (params_.do_pass_) - { - if (params_.do_pass_ == 1) - { - video_enc->flags |= CODEC_FLAG_PASS1; - } - else - { - video_enc->flags |= CODEC_FLAG_PASS2; - } - } - - std::strncpy( os_->fmt_cxt_->filename, filename_.c_str(), 1023 ); - - if ( avio_open( &os_->fmt_cxt_->pb, filename_.c_str(), AVIO_FLAG_WRITE ) < 0 ) - { - std::cerr << "ffmpeg: couldn't open " << filename_ << " for writing\n"; - close(); - return false; - } - os_->file_opened_ = true; - - //dump_format( os_->fmt_cxt_, 1, filename_, 1 ); - - if ( avcodec_open2( video_enc, codec, nullptr ) < 0 ) - { - std::cerr << "ffmpeg: couldn't open codec\n"; - close(); - return false; - } - os_->codec_opened_ = true; - - if ( avformat_write_header( os_->fmt_cxt_, nullptr ) < 0 ) - { - std::cerr << "ffmpeg: couldn't write header\n"; - close(); - return false; - } - - return true; -} - - -//: Close the stream -void -vidl_ffmpeg_ostream:: -close() -{ - //delete os_->video_rc_eq_; - //os_->video_rc_eq_ = NULL; - - if ( os_->fmt_cxt_ ) { - - // flush out remaining packets refer to - // http://stackoverflow.com/questions/17816532/creating-a-video-from-images-using-ffmpeg-libav-and-libx264 - AVCodecContext* codec = os_->fmt_cxt_->streams[0]->codec; - int got_packet = 1; - while (got_packet) - { - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = nullptr; - pkt.size = 0; - pkt.stream_index = 0; - - int ret = avcodec_encode_video2(codec, &pkt, nullptr, &got_packet); - - if (ret < 0) - { - std::cerr << "FFMPEG video encoding failed" << std::endl; - break; - } - if (got_packet) { - if (codec->coded_frame) { - pkt.pts = codec->coded_frame->pts; - } - if (codec->coded_frame && codec->coded_frame->key_frame) { - pkt.flags |= AV_PKT_FLAG_KEY; - } - av_interleaved_write_frame(os_->fmt_cxt_, &pkt); - av_packet_unref(&pkt); - - } - } - - if ( os_->file_opened_ ) { - av_write_trailer( os_->fmt_cxt_ ); - avio_close( os_->fmt_cxt_->pb ); - os_->file_opened_ = false; - } - - if ( os_->fmt_cxt_->nb_streams > 0 ) { - if ( os_->codec_opened_ ) { - for ( unsigned i = 0; i < os_->fmt_cxt_->nb_streams; ++i ) { - AVCodecContext* codec = os_->fmt_cxt_->streams[i]->codec; - if ( codec->stats_in ) { - av_freep( codec->stats_in ); - } - avcodec_close( codec ); - } - } - os_->codec_opened_ = false; - for ( unsigned i = 0; i < os_->fmt_cxt_->nb_streams; ++i ) { - av_free( os_->fmt_cxt_->streams[i] ); - } - } - - av_free( os_->fmt_cxt_ ); - os_->fmt_cxt_ = nullptr; - } -} - - -//: Return true if the stream is open for writing -bool -vidl_ffmpeg_ostream:: -is_open() const -{ - return os_->file_opened_; -} - - -//: Write and image to the stream -// \retval false if the image could not be written -bool -vidl_ffmpeg_ostream:: -write_frame(const vidl_frame_sptr& frame) -{ - if (!is_open()) { - // resize to the first frame - params_.size(frame->ni(),frame->nj()); - open(); - } - - AVCodecContext* codec = os_->fmt_cxt_->streams[0]->codec; - - if (unsigned( codec->width ) != frame->ni() || - unsigned( codec->height) != frame->nj() ) { - std::cerr << "ffmpeg: Input image has wrong size. Expecting (" - << codec->width << 'x' << codec->height << "), got (" - << frame->ni() << 'x' << frame->nj() << ")\n"; - return false; - } - - AVPixelFormat fmt = vidl_pixel_format_to_ffmpeg(frame->pixel_format()); - - vidl_pixel_format target_fmt = vidl_pixel_format_from_ffmpeg(codec->pix_fmt); - static vidl_frame_sptr temp_frame = new vidl_shared_frame(nullptr,frame->ni(),frame->nj(),target_fmt); - - AVFrame* out_frame = av_frame_alloc(); - //avcodec_get_frame_defaults( &out_frame ); - - // The frame is in the correct format to encode directly - if ( codec->pix_fmt == fmt ) - { - avpicture_fill((AVPicture*)out_frame, (uint8_t*) frame->data(), - fmt, frame->ni(), frame->nj()); - //int ret = av_image_fill_arrays(out_frame->data, out_frame->linesize, (uint8_t*)frame->data(), - // fmt, frame->ni(), frame->nj(), 1); - } - else - { - if (!temp_frame->data()) { - unsigned ni = frame->ni(); - unsigned nj = frame->nj(); - unsigned out_size = vidl_pixel_format_buffer_size(ni,nj,target_fmt); - temp_frame = new vidl_memory_chunk_frame(ni, nj, target_fmt, - new vil_memory_chunk(out_size, VIL_PIXEL_FORMAT_BYTE)); - } - // try conversion with FFMPEG functions - if (!vidl_ffmpeg_convert(frame, temp_frame)) { - // try conversion with vidl functions - if (!vidl_convert_frame(*frame, *temp_frame)) { - std::cout << "unable to convert " << frame->pixel_format() << " to "<data(), - codec->pix_fmt, frame->ni(), frame->nj()); - //int ret = av_image_fill_arrays(out_frame->data, out_frame->linesize, (uint8_t*)temp_frame->data(), - // fmt, temp_frame->ni(), temp_frame->nj(), 1); - //ret = 0; - } - - AVPacket pkt; - av_init_packet( &pkt ); - pkt.data = nullptr; - pkt.size = 0; - pkt.stream_index = 0; - - out_frame->pts = os_->cur_frame_; - out_frame->width = codec->width; - out_frame->height = codec->height; - out_frame->format = codec->pix_fmt; - - int got_packet; - int ret = avcodec_encode_video2( codec, &pkt, out_frame, &got_packet ); - - if ( ret < 0 ) - { - std::cerr << "FFMPEG video encoding failed" <coded_frame ) { - pkt.pts = codec->coded_frame->pts; - } - if ( codec->coded_frame && codec->coded_frame->key_frame ) { - pkt.flags |= AV_PKT_FLAG_KEY; - } - av_interleaved_write_frame( os_->fmt_cxt_, &pkt ); - av_packet_unref(&pkt); - } - - ++os_->cur_frame_; - return true; -} - -#endif // vidl_ffmpeg_ostream_v56_hxx_ From b6c35bcd27e027ee2966e4bb0054a9d2be012b57 Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Mon, 22 Jul 2019 16:02:36 -0400 Subject: [PATCH 20/22] Revert "Cleanup patch" This reverts commit 14007ca5b1509b6c597284f7bed6c4271c207d31. --- Patches/VXL/FindFFMPEG.cmake | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Patches/VXL/FindFFMPEG.cmake b/Patches/VXL/FindFFMPEG.cmake index c6c8eb7e..f3569e61 100644 --- a/Patches/VXL/FindFFMPEG.cmake +++ b/Patches/VXL/FindFFMPEG.cmake @@ -72,16 +72,20 @@ else() ) if( FFMPEG_avcodec_LIBRARY ) - if( FFMPEG_avformat_LIBRARY ) - set( FFMPEG_FOUND "YES" ) - set( FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} ${FFMPEG_avcodec_LIBRARY} ) - if( FFMPEG_avutil_LIBRARY ) - set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_avutil_LIBRARY} ) - endif() - if( FFMPEG_swscale_LIBRARY ) - set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_swscale_LIBRARY} ) - endif() + if( FFMPEG_avformat_LIBRARY ) + + set( FFMPEG_FOUND "YES" ) + set( FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} ${FFMPEG_avcodec_LIBRARY} ) + if( FFMPEG_avutil_LIBRARY ) + set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_avutil_LIBRARY} ) + endif() + if( FFMPEG_swscale_LIBRARY ) + set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_swscale_LIBRARY} ) endif() + endif() + endif() + +endif() endif() From 31df308e9cf866a83502f2424518906899bd299c Mon Sep 17 00:00:00 2001 From: Matt Dawkins Date: Mon, 22 Jul 2019 16:02:57 -0400 Subject: [PATCH 21/22] Revert "Patch ffmpeg issue" This reverts commit 13fc389bdb3fb408999c335aa123c6f99049b693. --- CMake/External_VXL.cmake | 4 -- Patches/VXL/FindFFMPEG.cmake | 91 ------------------------------------ Patches/VXL/Patch.cmake | 10 ---- 3 files changed, 105 deletions(-) delete mode 100644 Patches/VXL/FindFFMPEG.cmake delete mode 100644 Patches/VXL/Patch.cmake diff --git a/CMake/External_VXL.cmake b/CMake/External_VXL.cmake index 3c208a1f..495e02e0 100644 --- a/CMake/External_VXL.cmake +++ b/CMake/External_VXL.cmake @@ -97,10 +97,6 @@ ExternalProject_Add(VXL DOWNLOAD_NAME ${VXL_dlname} ${COMMON_EP_ARGS} ${COMMON_CMAKE_EP_ARGS} - PATCH_COMMAND ${CMAKE_COMMAND} - -DVXL_patch:PATH=${fletch_SOURCE_DIR}/Patches/VXL - -DVXL_source:PATH=${fletch_BUILD_PREFIX}/src/VXL - -P ${fletch_SOURCE_DIR}/Patches/VXL/Patch.cmake CMAKE_ARGS ${KWIVER_ARGS_COMMON} ${VXL_ARGS_GUI} diff --git a/Patches/VXL/FindFFMPEG.cmake b/Patches/VXL/FindFFMPEG.cmake deleted file mode 100644 index f3569e61..00000000 --- a/Patches/VXL/FindFFMPEG.cmake +++ /dev/null @@ -1,91 +0,0 @@ -# Find the FFmpeg library -# -# Sets -# FFMPEG_FOUND. If false, don't try to use ffmpeg -# FFMPEG_FOUND_SEVERAL. If true, there are several directories with headers (not only ../ffmpeg/) -# FFMPEG_INCLUDE_DIR -# FFMPEG_LIBRARIES - -set( FFMPEG_FOUND "NO" ) - -find_path( FFMPEG_INCLUDE1_DIR ffmpeg/avcodec.h - /usr/include - /usr/local/include -) -find_path( FFMPEG_INCLUDE2_DIR libavcodec/avcodec.h - /usr/include - /usr/local/include -) -if( FFMPEG_INCLUDE1_DIR ) - set( FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE1_DIR} ) -endif() - -if( FFMPEG_INCLUDE2_DIR ) - set( FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE2_DIR} ) -endif() - -if( FFMPEG_INCLUDE_DIR AND FFMPEG_INCLUDE2_DIR ) - set( FFMPEG_FOUND_SEVERAL "YES" ) -else() - set( FFMPEG_FOUND_SEVERAL "NO" ) -endif() - -find_program( FFMPEG_CONFIG ffmpeg-config - /usr/bin - /usr/local/bin - ${HOME}/bin -) - -if( FFMPEG_CONFIG ) - exec_program( ${FFMPEG_CONFIG} ARGS "--libs avformat" OUTPUT_VARIABLE FFMPEG_LIBS ) - set( FFMPEG_FOUND "YES" ) - set( FFMPEG_LIBRARIES "${FFMPEG_LIBS}" ) - -else() - - find_library( FFMPEG_avcodec_LIBRARY avcodec - /usr/lib - /usr/local/lib - /usr/lib64 - /usr/local/lib64 - ) - - find_library( FFMPEG_avformat_LIBRARY avformat - /usr/lib - /usr/local/lib - /usr/lib64 - /usr/local/lib64 - ) - - find_library( FFMPEG_avutil_LIBRARY avutil - /usr/lib - /usr/local/lib - /usr/lib64 - /usr/local/lib64 - ) - - find_library( FFMPEG_swscale_LIBRARY swscale - /usr/lib - /usr/local/lib - /usr/lib64 - /usr/local/lib64 - ) - - if( FFMPEG_avcodec_LIBRARY ) - if( FFMPEG_avformat_LIBRARY ) - - set( FFMPEG_FOUND "YES" ) - set( FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} ${FFMPEG_avcodec_LIBRARY} ) - if( FFMPEG_avutil_LIBRARY ) - set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_avutil_LIBRARY} ) - endif() - if( FFMPEG_swscale_LIBRARY ) - set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_swscale_LIBRARY} ) - endif() - - endif() - endif() - -endif() - -endif() diff --git a/Patches/VXL/Patch.cmake b/Patches/VXL/Patch.cmake deleted file mode 100644 index 1a4005a5..00000000 --- a/Patches/VXL/Patch.cmake +++ /dev/null @@ -1,10 +0,0 @@ -#+ -# This file is called as CMake -P script for the patch step of -# External_VXL.cmake to fix a minor ffmpeg find flag -#- - -message("Patching VXL in ${VXL_source}") - -file(COPY ${VXL_patch}/FindFFMPEG.cmake - DESTINATION ${VXL_source}/config/cmake/Modules/NewCMake/ -) From ebe73e026853b4fbfe1b56f2a2388acd6a9668a2 Mon Sep 17 00:00:00 2001 From: David Stoup Date: Wed, 17 Jul 2019 16:47:10 -0400 Subject: [PATCH 22/22] Peg the vxl hash to today's master Conflicts: CMake/fletch-tarballs.cmake --- CMake/fletch-tarballs.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMake/fletch-tarballs.cmake b/CMake/fletch-tarballs.cmake index b7f08a3d..6c993797 100644 --- a/CMake/fletch-tarballs.cmake +++ b/CMake/fletch-tarballs.cmake @@ -429,9 +429,9 @@ endif() list(APPEND fletch_external_sources VTK) # VXL -set(VXL_version "c3fd27959f51e0469a7a6075e975f245ac306f3d") +set(VXL_version "ecc0202f4f9eccaffa89b061e9567a20597fd10e") set(VXL_url "https://github.com/vxl/vxl/archive/${VXL_version}.zip") -set(VXL_md5 "9ae63bb158ae3e5e2104152093a4c46c") +set(VXL_md5 "43f59314889597ad5e84da9d023f0ee7") set(VXL_dlname "vxl-${VXL_version}.zip") list(APPEND fletch_external_sources VXL)