Browse Source

powered by spray paint

what doesn't kill you makes you high
boyska 7 years ago
parent
commit
40d353a37a
5 changed files with 262 additions and 3 deletions
  1. 18 3
      .gitignore
  2. 19 0
      CMakeLists.txt
  3. 159 0
      bs_dsp.cu
  4. 3 0
      getfiles
  5. 63 0
      lines.cpp

+ 18 - 3
.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

+ 19 - 0
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} )

+ 159 - 0
bs_dsp.cu

@@ -0,0 +1,159 @@
+#include<cuda.h>
+#include<opencv2/opencv.hpp>
+
+#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<<<grid,threads>>>(d_U,d_V,data);
+	}
+	cudaGammaCorrection<<<grid,threads>>>(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;
+}

+ 3 - 0
getfiles

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+rsync -r www.degenerazione.xyz::avana/scanner/sagoma/ "$(dirname $0)/files/"

+ 63 - 0
lines.cpp

@@ -0,0 +1,63 @@
+#include<opencv2/opencv.hpp>
+
+int main(int argc, char *argv[])
+{
+	cv::Mat img=cv::imread("files/masckera.png",CV_LOAD_IMAGE_GRAYSCALE);
+
+	std::vector< std::vector<cv::Point> > contours;
+	std::vector<cv::Vec4i> 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<cv::Point> 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;
+}