-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from rbebb/beta
Beta Ready for Prime Time
- Loading branch information
Showing
9 changed files
with
368 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
int* convolute_image(int *img, int *dims, double **kernel, int k); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.