From 40d353a37a17d3fc47d212432f0ada7fd8f2eecd Mon Sep 17 00:00:00 2001 From: boyska Date: Thu, 5 Jan 2017 13:40:59 +0100 Subject: [PATCH] powered by spray paint what doesn't kill you makes you high --- .gitignore | 21 ++++++- CMakeLists.txt | 19 ++++++ bs_dsp.cu | 159 +++++++++++++++++++++++++++++++++++++++++++++++++ getfiles | 3 + lines.cpp | 63 ++++++++++++++++++++ 5 files changed, 262 insertions(+), 3 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 bs_dsp.cu create mode 100755 getfiles create mode 100644 lines.cpp diff --git a/.gitignore b/.gitignore index 06ded9d..f28dfc5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,23 @@ -build +# editor swap files .*.sw* .*~ *~ -/build/ -*.txt + +# images *.jpg *.png +/files/ + +# cmake +CMakeCache.txt +CMakeFiles +CMakeScripts +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +/build/ + +# executables +/lines diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1fc4e68 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required( VERSION 2.8 ) +project( bs_dsp ) + +# Eigen library +include_directories( "/usr/include/eigen3/" ) + +# OpenCV +find_package( OpenCV 3.1 REQUIRED ) + +# CUDA +find_package( CUDA ) +if (CUDA_FOUND) + include( FindCUDA ) + cuda_add_executable( bs_dsp bs_dsp.cu ) + target_link_libraries( bs_dsp ${OpenCV_LIBS} ) +endif (CUDA_FOUND) + +add_executable( lines lines.cpp ) +target_link_libraries( lines ${OpenCV_LIBS} ) diff --git a/bs_dsp.cu b/bs_dsp.cu new file mode 100644 index 0000000..fc88a25 --- /dev/null +++ b/bs_dsp.cu @@ -0,0 +1,159 @@ +#include +#include + +#define cudaASSERT(ans) \ +{ \ + cudaAssert((ans), __FILE__, __FUNCTION__, __LINE__); \ +} + +typedef struct +{ + float hs; // space bandwidth + float hc; // color bandwidth + + int iterations; // number of iterations + + // device parameters + size_t bsize; // threads per block (x and y dimensions) + + // gamma correction + float exponent; + + // image dimensions + int rows; + int cols; +} MSdata; + + +// informs the user when a CUDA error occurs (optionally, also stops the program execution) +void cudaAssert(cudaError_t code, const char *file, const char *fn, int line, bool abort=false) +{ + if( cudaSuccess!=code ) + { + fprintf(stderr,"[%s() @ %s:%d] %s\n",fn,file,line,cudaGetErrorString(code)); + if( abort ) + { + exit(code); + } + } +} + +// CUDA kernel for the mean shift algorithm for grayscale images +__global__ void cudaMeanShift1D(unsigned char *U, unsigned char *V, const MSdata data) +{ + // compute pixel coordinates + const int x=blockDim.x*blockIdx.x+threadIdx.x; + const int y=blockDim.y*blockIdx.y+threadIdx.y; + + // square space and color "bandwidths" + const int hs=data.hs*data.hs; + const int hc=data.hc*data.hc; + + #define e_U(i,j) U[(j)*data.cols+(i)] + #define e_V(i,j) V[(j)*data.cols+(i)] + if( data.cols>x && data.rows>y ) + { + float I=0.0f,W=0.0f,w; + + // compute the neighborhood size of the pixel (x,y) + const int dx_min=(data.hs>x)?x:data.hs; + const int dy_min=(data.hs>y)?y:data.hs; + const int dx_max=((data.hs+x)>=data.cols)?(data.cols-x-1):data.hs; + const int dy_max=((data.hs+y)>=data.rows)?(data.rows-y-1):data.hs; + + // for each neighbor (i,j) of the pixel (x,y), + for( int dx=-dx_min; dx_max>=dx; dx++) + { + const int i=x+dx; + for( int dy=-dy_min; dy_max>=dy; dy++ ) + { + const int j=y+dy; + + // compute the kernel value at -||(X-X_{i})/h||^2 + const float dI=e_U(i,j)-e_V(x,y); + if( hs>=(dx*dx+dy*dy) && hc>=(dI*dI) ) + { + w=1.0f;//__expf(-(dx*dx+dy*dy)/hs-dI*dI/hc); + W+=w; + I+=w*e_U(i,j); + } + } + } + + // compute the new intensity value + e_V(x,y)=round(I/W); + } + #undef e_U + #undef e_V +} + +// CUDA kernel for gamma correction +__global__ void cudaGammaCorrection(unsigned char *U, const MSdata data) +{ + // compute pixel coordinates + const int x=blockDim.x*blockIdx.x+threadIdx.x; + const int y=blockDim.y*blockIdx.y+threadIdx.y; + + #define e_U(i,j) U[(j)*data.cols+(i)] + if( data.cols>x && data.rows>y ) + { + float value=0.00392156862f*e_U(x,y); + value=255.0f*powf(value,data.exponent); + e_U(x,y)=round(value); + } + #undef e_U +} + + +int main(int argc, char **argv) +{ + cv::Mat img=cv::imread("../prospettiva.jpg"); + cv::cvtColor(img,img,CV_BGR2GRAY); + + MSdata data; + data.bsize=32; + data.iterations=50; + data.hc=10; + data.hs=3; + data.cols=img.cols; + data.rows=img.rows; + data.exponent=0.85f; + + // device arrays + unsigned char *d_U,*d_V; + + // memory allocation on device + size_t bytes=data.rows*data.cols*sizeof(unsigned char); + cudaASSERT( cudaMalloc((void**)&d_U,bytes) ); + cudaASSERT( cudaMalloc((void**)&d_V,bytes) ); + + // grid and blocks geometry + dim3 grid(1,1,1); + dim3 threads(data.bsize,data.bsize,1); + grid.x=(data.cols/data.bsize)+((data.cols%data.bsize)?1:0); + grid.y=(data.rows/data.bsize)+((data.rows%data.bsize)?1:0); + + // device arrays initialization + cudaASSERT( cudaMemcpy(d_U,img.data,bytes,cudaMemcpyHostToDevice) ); + cudaASSERT( cudaMemcpy(d_V,img.data,bytes,cudaMemcpyHostToDevice) ); + + // mean shift iterations on the GPU + for( int k=0; data.iterations>k; k++) + { + cudaMeanShift1D<<>>(d_U,d_V,data); + } + cudaGammaCorrection<<>>(d_V,data); + + // retrieve result from device + cudaASSERT( cudaMemcpy(img.data,d_V,bytes,cudaMemcpyDeviceToHost) ); + + // free device memory resources + cudaASSERT( cudaFree(d_U) ); + cudaASSERT( cudaFree(d_V) ); + + cv::Mat bw; + cv::threshold(img,bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); + + cv::imwrite("../modified.jpg",bw); + return 0; +} diff --git a/getfiles b/getfiles new file mode 100755 index 0000000..ad5f9fd --- /dev/null +++ b/getfiles @@ -0,0 +1,3 @@ +#!/bin/bash + +rsync -r www.degenerazione.xyz::avana/scanner/sagoma/ "$(dirname $0)/files/" diff --git a/lines.cpp b/lines.cpp new file mode 100644 index 0000000..6fa6434 --- /dev/null +++ b/lines.cpp @@ -0,0 +1,63 @@ +#include + +int main(int argc, char *argv[]) +{ + cv::Mat img=cv::imread("files/masckera.png",CV_LOAD_IMAGE_GRAYSCALE); + + std::vector< std::vector > contours; + std::vector hierarchy; + cv::findContours(img,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE); + + cv::drawContours(img,contours,-1,cv::Scalar(255,255,255),5); + + if( 1!=contours.size() ) + { + std::cout << "non ci piace" << std::endl; + return -1; + } + + std::vector hull; + cv::convexHull(cv::Mat(contours[0]),hull,false); + + int i; + int idx[4]={0}; + int distance[2]={0}; + for( i=0; hull.size()>i; i++ ) + { + cv::Point one=hull[i]; + cv::Point two=hull[(i+1)%hull.size()]; + int d=pow(one.x-two.x,2)+pow(one.y-two.y,2); + if( d>distance[0] ) + { + idx[1]=idx[0]; + idx[3]=(idx[1]+1)%hull.size(); + idx[0]=i; + idx[2]=(idx[0]+1)%hull.size(); + distance[1]=distance[0]; + distance[0]=d; + } + else if( d>distance[1] ) + { + idx[1]=i; + idx[3]=(i+1)%hull.size(); + distance[1]=d; + } + } + + cv::circle(img,hull[idx[0]],30,255,-1); + cv::circle(img,hull[(idx[0]+1)%hull.size()],30,255,-1); + + cv::circle(img,hull[idx[1]],20,255,-1); + cv::circle(img,hull[(idx[1]+1)%hull.size()],20,255,-1); + + + std::cout << hull.size() << ", " << contours[0].size() << std::endl; + std::cout + << "(" << idx[0] << "," << distance[0] << ") -- " + << "(" << idx[1] << "," << distance[1] << ")" << std::endl; + cv::namedWindow("test",CV_WINDOW_NORMAL); + cv::imshow("test",img); + cv::waitKey(0); + + return 0; +}