Skip to content

Commit

Permalink
Merge pull request #16 from rbebb/beta
Browse files Browse the repository at this point in the history
Beta Ready for Prime Time
  • Loading branch information
rbebb authored Aug 15, 2019
2 parents 8cc91dc + d5cee57 commit 508b13a
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 172 deletions.
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# editor files
.vscode/

# testing folder
test/

# object and executable files
**/*.x
**/*.o

# output files
videoProcessingResults.o*

# images and videos
*.jpg
*.avi
*.mp4
48 changes: 48 additions & 0 deletions convolution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include <iostream>
#include <cstdlib>
#include <string>
#include <omp.h>
#include "convolution.hpp"

using namespace std;

/**
* Function that applies a supplied kernel to a supplied image.
*
* @param *img buffer containing image data
* @param *dims array of length 2 holding height and width of the image
* @param **kernel odd-sized square matrix holding transformation kernel
* @param k width of the kernel
* @return *filtered filtered image
*/
int* convolute_image(int *img, int *dims, double **kernel, int k) {
double a;
int *filtered;

filtered = (int*) malloc(dims[0] * dims[1] * sizeof(int));

#pragma omp parallel for shared(filtered) private(a)
for(int i = 0; i < dims[0]; i++) {
for(int j = 0; j < dims[1]; j++) {
a = 0.0;

for(int ki = -(k/2); ki <= (k/2); ki++) {
for(int kj = -(k/2); kj <= (k/2); kj++) {
if((i + ki < 0) || (j + kj < 0) || (i + ki > dims[0] - 1) || (j + kj > dims[1] - 1)) {
continue;
} else {
double kval = kernel[kj + (k/2)][ki + (k/2)];
double ival = img[(i + ki) * dims[1] + (j + kj)];
a += kval * ival;
}
}
}

if(a > 255) a = 255;
if(a < 0) a = 0;
filtered[(i * dims[1]) + j] = (int) a;
}
}

return filtered;
}
1 change: 1 addition & 0 deletions convolution.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int* convolute_image(int *img, int *dims, double **kernel, int k);
70 changes: 70 additions & 0 deletions imageTools.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <iostream>
#include <string>
#include <cmath>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int* imageToMat(string filename, int* dims){
Mat image;
image = imread(filename, CV_LOAD_IMAGE_COLOR);

Mat gray_image;
cvtColor(image, gray_image, CV_BGR2GRAY);

// Check for invalid input
if (!image.data)
{
cout << "Could not open or find the image" << std::endl ;
int* temp;
return temp;
}
int width = gray_image.size().width;
int height = gray_image.size().height;
dims[0] = height;
dims[1] = width;

cout << "Height: " << dims[0] << endl;
cout << "Width : " << dims[1] << endl;
//namedWindow( "Original Image", WINDOW_AUTOSIZE );// Create a window for display.
//imshow( "Original Image", gray_image ); // Show our image inside it.


//allocate 2d array
int *matrix;
matrix = (int*) malloc(height*width*sizeof(*matrix));
for (int i = 0; i < height; i++){
for(int j = 0; j < width; j++){
int intensity = gray_image.at<uchar>(i,j);
if (intensity > 254) {
intensity = 254;
}
if (intensity < 0) {
intensity = 0;
}
matrix[i*width+j] = intensity;
}
}

return matrix;
}


void matToImage(string filename, int* mat, int* dims){
int height = dims[0];
int width = dims[1];
Mat image(height, width, CV_8UC1, Scalar(0,0,0));

for(int i = 0; i < height; i++){
for(int j = 0; j < width; j++){
image.at<uchar>(i,j) = (int) mat[i*width+j];
}
}
//namedWindow( "Processed Image", WINDOW_AUTOSIZE );// Create a window for display.

//imshow( "Processed Image", image ); // Show our image inside it.
imwrite(filename, image);
//waitKey(0); // Wait for a keystroke in the window
return;
}
226 changes: 226 additions & 0 deletions mW.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
#include <iostream>
#include <cstdlib>
#include <string>
#include <cmath>
#include <omp.h>
#include "mpi.h"
#include "convolution.hpp"
#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/video/video.hpp"

using namespace cv;
using namespace std;

int main(int argc, char** argv) {

// Start up MPI
int numranks, myrank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numranks);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
MPI_Status status;

// Create our kernel for all ranks
// Change this value to set the size of our desired kernel
int kernel_dimensions = 5;
double** kernel = (double**) malloc(kernel_dimensions * sizeof(double*));
for (int i = 0; i < kernel_dimensions; i++) {
kernel[i] = (double*) malloc(kernel_dimensions * sizeof(double));
}
double value = 1.0/9.0;
for(int i = 0; i < kernel_dimensions; i++) {
for (int j = 0; j < kernel_dimensions; j++) {
kernel[i][j] = value;
}
}

int* mat;
int* dims = (int*) malloc(2*sizeof(int));
dims[0] = 0;
dims[1] = 0;
int* answer;

if (myrank == 0) {
int num_frames = 0;
int current_frame = 0;

int rowsSent = 0;
int rowsReceived = 0;

// OpenCV calls to open the video, get number of frames, get dimensions
VideoCapture videoIn("/home/bebbr/test.mp4");

// Check if file can open
if (!videoIn.isOpened()) {
cout << "Error opening file" << std::endl;
}

num_frames = videoIn.get(CV_CAP_PROP_FRAME_COUNT);

Mat temp;
videoIn >> temp;
dims[0] = temp.size().height;
dims[1] = temp.size().width;

// Make sure everyone knows the resolution
MPI_Bcast(dims, 2, MPI_INT, 0, MPI_COMM_WORLD);

for (int i = 1; i < numranks; i++) {
// Get current frame
videoIn.set(CV_CAP_PROP_POS_FRAMES, current_frame);

Mat color;
videoIn >> color;

// Convert to grayscale
Mat grayImage;
cvtColor(color, grayImage, CV_BGR2GRAY);

// Get height and width of video
int width = grayImage.size().width;
int height = grayImage.size().height;
dims[0] = height;
dims[1] = width;

// Allocate 2D array
mat = (int*) malloc(height*width*sizeof(*mat));
for (int j = 0; j < height; j++) {
for (int k = 0; k < width; k++) {
int intensity = grayImage.at<uchar>(j,k);
if (intensity > 255) {
intensity = 255;
}
if (intensity < 0) {
intensity = 0;
}
mat[j*width+k] = intensity;
}
}

// Send matrix to worker to eventually convolve the desired frame
MPI_Send(mat, dims[0] * dims[1], MPI_INT, i, 0, MPI_COMM_WORLD);
current_frame++;
rowsSent++;
free(mat);
}

// Set video output file name, encoding, FPS, and resolution
VideoWriter videoOut("output.avi", CV_FOURCC('M', 'J', 'P', 'G'), 30, Size(dims[1], dims[0]));

int ranksWorking = numranks - 1;

while (1) {
for (int i = 1; i <= ranksWorking; i++) {
answer = (int*) malloc(dims[0] * dims[1] * sizeof(int));
// Receive the convolved frame from the worker
MPI_Recv(answer, dims[0] * dims[1], MPI_INT, i, 0, MPI_COMM_WORLD, &status);
rowsReceived++;

// Convert array back to Mat object
Mat frame(dims[0], dims[1], CV_8UC1, Scalar(0, 0, 0));
for (int j = 0; j < dims[0]; j++) {
for (int k = 0; k < dims[1]; k++) {
frame.at<uchar>(j, k) = (int) answer[j*dims[1]+k];
}
}

// Save video as image and save image to frame of video
imwrite("test.jpg", frame);
Mat img = imread("test.jpg");
videoOut.write(img);

free(answer);
}


if (rowsReceived >= num_frames-1) {
mat = (int*) malloc(dims[0]*dims[1]*sizeof(*mat));
mat[0] = -1;
for (int i = 1; i < numranks; i++) {
// If there are no more frames to convolve, let the other ranks know
MPI_Send(mat, dims[1] * dims[0], MPI_INT, i, 0, MPI_COMM_WORLD);
}
free(mat);
break;
}

ranksWorking = 0;

for(int i = 1; i < numranks; i++) {
if (rowsSent <= num_frames-1) {
// Get current frame
videoIn.set(CV_CAP_PROP_POS_FRAMES, current_frame);

Mat color;
videoIn >> color;

// Convert to grayscale
Mat grayImage;
cvtColor(color, grayImage, CV_BGR2GRAY);

// Get height and width of frame
int width = grayImage.size().width;
int height = grayImage.size().height;
dims[0] = height;
dims[1] = width;

// Allocate 2D array
mat = (int*) malloc(height*width*sizeof(*mat));
for (int j = 0; j < height; j++) {
for (int k = 0; k < width; k++) {
int intensity = grayImage.at<uchar>(j,k);
if (intensity > 255) {
intensity = 255;
}
if (intensity < 0) {
intensity = 0;
}
mat[j*width+k] = intensity;
}
}

// Send matrix to worker to eventually convolve the desired frame
MPI_Send(mat, dims[1] * dims[0], MPI_INT, i, 0, MPI_COMM_WORLD);
current_frame++;
rowsSent++;
ranksWorking++;
free(mat);
}
}
}

// Close VideoCapture and close all frames
videoIn.release();
videoOut.release();
destroyAllWindows();

}

if (myrank != 0) {
// Make sure everyone knows the resolution
MPI_Bcast(dims, 2, MPI_INT, 0, MPI_COMM_WORLD);
// Array to store original frame
mat = (int*) malloc(dims[0] * dims[1] * sizeof(int));
// Array to store convolved frame
answer = (int*) malloc(dims[0] * dims[1] * sizeof(int));
while (1) {
// Receive matrix to convolve from the master rank
MPI_Recv(mat, dims[0] * dims[1], MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
if (mat[0] == -1) {
break;
}

// Method call to perform convolution with mat and kernel
answer = convolute_image(mat, dims, kernel, kernel_dimensions);
// Send convolved frame back to the master rank
MPI_Send(answer, dims[0] * dims[1], MPI_INT, 0, 0, MPI_COMM_WORLD);
}
}


MPI_Finalize();
return 0;
}
12 changes: 4 additions & 8 deletions makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
CC=gcc
CPP=g++
LDC=gcc
LDP=g++
CPP=tau_cxx.sh
LDP=tau_cxx.sh
LD_FLAGS = -fopenmp -lstdc++ -lopencv_core -lopencv_highgui -lopencv_imgproc
FLAGS= -fopenmp -I/usr/include/opencv
PROGC = videoProcessing.cx
OBJSC = videoProcessing.o imageTools.o
PROGC = mW.x
OBJSC = mW.o convolution.o

RM = /bin/rm

Expand All @@ -14,8 +12,6 @@ all: $(PROGC)

$(PROGC): $(OBJSC)
$(LDP) $^ $(LD_FLAGS) -o $@
%.o: %.c
$(CC) $(FLAGS) -c $^ -o $@
%.o: %.cpp
$(CPP) $(FLAGS) -c $^ -o $@

Expand Down
Loading

0 comments on commit 508b13a

Please sign in to comment.