2x2 box filter
parent
8cb9bc8b59
commit
f77f41c9c2
@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <stdexcept> // std::runtime_error
|
||||||
|
#include <opencv2/opencv.hpp> // all opencv header
|
||||||
|
// TODO: add openmp support
|
||||||
|
|
||||||
|
namespace hdrplus
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
cv::Mat box_filter_2x2( cv::Mat src_image )
|
||||||
|
{
|
||||||
|
// https://stackoverflow.com/questions/34042112/opencv-mat-data-member-access
|
||||||
|
const T* src_image_ptr = (T*)src_image.data;
|
||||||
|
int src_height = src_image.size().height;
|
||||||
|
int src_width = src_image.size().width;
|
||||||
|
int src_step = src_image.step1();
|
||||||
|
|
||||||
|
if ( src_height % 2 != 0 || src_width % 2 != 0 )
|
||||||
|
{
|
||||||
|
throw std::runtime_error( std::string( __FILE__ ) + "::" + __func__ + " source image need to have size multiplier of 2\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::Mat dst_image( src_height / 2, src_width / 2, src_image.type() );
|
||||||
|
T* dst_image_ptr = (T*)dst_image.data;
|
||||||
|
//int dst_height = dst_image.size().height;
|
||||||
|
//int dst_width = dst_image.size().width;
|
||||||
|
int dst_step = dst_image.step1();
|
||||||
|
|
||||||
|
// -03 should be enough to optimize below code
|
||||||
|
for ( int row_i = 0; row_i < src_height; row_i += 2 )
|
||||||
|
{
|
||||||
|
for ( int col_i = 0; col_i < src_width; col_i += 2 )
|
||||||
|
{
|
||||||
|
T box_sum = src_image_ptr[ ( row_i + 0 ) * src_step + col_i + 0 ] + \
|
||||||
|
src_image_ptr[ ( row_i + 0 ) * src_step + col_i + 1 ] + \
|
||||||
|
src_image_ptr[ ( row_i + 1 ) * src_step + col_i + 0 ] + \
|
||||||
|
src_image_ptr[ ( row_i + 1 ) * src_step + col_i + 1 ];
|
||||||
|
T box_avg = ( box_sum + T(3) ) / 4; // take ceiling
|
||||||
|
dst_image_ptr[ ( row_i / 2 ) * dst_step + ( col_i / 2 ) ] = box_avg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cv::Mat internally use reference count. Will not copy by value here
|
||||||
|
return dst_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace hdrplus
|
@ -0,0 +1,49 @@
|
|||||||
|
#include <cstdio>
|
||||||
|
#include <vector>
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include "hdrplus/utility.h"
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void print_cvmat( cv::Mat image )
|
||||||
|
{
|
||||||
|
int height = image.size().height;
|
||||||
|
int width = image.size().width;
|
||||||
|
|
||||||
|
for ( int row_i = 0; row_i < height; ++row_i )
|
||||||
|
{
|
||||||
|
for ( int col_i = 0; col_i < width; ++col_i )
|
||||||
|
{
|
||||||
|
printf("%2.d ", int( image.at<T>( row_i, col_i ) ) );
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_box_filter_2x2()
|
||||||
|
{
|
||||||
|
// Intialize input data
|
||||||
|
int src_width = 10;
|
||||||
|
int src_height = 6;
|
||||||
|
std::vector<uint16_t> src_data( src_width, src_height );
|
||||||
|
|
||||||
|
for ( int i = 0; i < src_width * src_height; ++i )
|
||||||
|
{
|
||||||
|
src_data[ i ] = i+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create input cv::mat
|
||||||
|
cv::Mat src_image( src_height, src_width, CV_16U, src_data.data() );
|
||||||
|
|
||||||
|
printf("src cv::Mat is \n");
|
||||||
|
print_cvmat<uint16_t>( src_image );
|
||||||
|
|
||||||
|
cv::Mat dst_image = hdrplus::box_filter_2x2<uint16_t>( src_image );
|
||||||
|
|
||||||
|
printf("dst cv::Mat is \n");
|
||||||
|
print_cvmat<uint16_t>( dst_image );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test_box_filter_2x2();
|
||||||
|
}
|
Loading…
Reference in New Issue