Split image frame into 8*8 for DCT using OpenCV and C++ - c++

I need to pass fullPath into method FrameTo8by8(). In FrameTo8by8(), it will split the every frame into 8*8 blocks. (E.g. My video resolution is 1280*720 = 921,600. After that 921,600 / 64(8*8) = 14,400. So there will be total of 14,400 blocks of 8*8).
VideoSplitEngine.h
class VideoSplitEngine
{
public:
static VideoCapture capture;
static Mat fullimage;
//Default constructor
VideoSplitEngine();
//Declare a virtual destructor:
virtual ~VideoSplitEngine();
//Method
Mat Start();
void FrameTo8by8() const;
string GetFilePath() const;
private:
};
VideoSplitEngine.cpp
#include "StdAfx.h"
#include "VideoSplitEngine.h"
#include "UserInfo.h"
#include "Common.h"
VideoCapture VideoSplitEngine::capture;
Mat VideoSplitEngine::fullimage;
Mat VideoSplitEngine::Start()
string VideoSplitEngine::GetFilePath() const
{
cout<< endl;
cout << "Place video in Desktop and enter file name (e.g. vid.avi):" << endl;
cout<<"----------------------------------------------------------"<< endl;
//Get user desktop file path
string fullPath;
string userProfile = getenv("userprofile"); //GetEnvironmentVariable() is to get current userprofile (e.g."C:\Users\L30807")
string path = userProfile + "\\Desktop\\";
string vid;
getline (cin, vid); //Prompt to input file name
fullPath = path + vid;
capture.open(fullPath); //Read video
cout<< endl;
return fullPath;
}
Mat VideoSplitEngine::Start()
{
while(1)
{
bool bSuccess = capture.read(fullimage); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "End of video" << endl;
destroyWindow("Original Video");
break;
}
imshow("Original Video", fullimage); //show the frame in "Original Video" window
if(waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return fullimage;
}
void VideoSplitEngine::FrameTo8by8() const
{
namedWindow("Original", CV_WINDOW_AUTOSIZE);
imshow("Original", fullimage);
int width = fullimage.size().width;
int height = fullimage.size().width;
cout << "Original image Width x Height is " << width << "x" << height << endl;
// Leave original alone, work on a copy
Mat dctImage = fullimage.clone();
// Step through the copied image with rectangles size 8x8
// For each block, split into planes, do dct, and merge back
// into the block. (This will affect the image from
// which the block is selected each time.)
for (int i = 0; i < height; i += 8)
{
for (int j = 0; j < width; j+= 8)
{
Mat block = dctImage(Rect(i, j, 8, 8));
vector<Mat> planes;
split(block, planes);
vector<Mat> outplanes(planes.size());
for (size_t k = 0; k < planes.size(); k++)
{
planes[k].convertTo(planes[k], CV_32FC1);
dct(planes[k], outplanes[k]);
outplanes[k].convertTo(outplanes[k], CV_8UC1);
}
merge(outplanes, block);
}
}
namedWindow("dctBlockImage");
imshow("dctBlockImage", dctImage);
waitKey(30);
}
I need help on how to split it or is there other methods to do it?

1.#berak is right.The prototype of function Rect() is Rect(x,y,width,height).So 'j' which refer to 'width' should be 'x'.(Actually I havn't found the prototype of Rect() from http://docs.opencv.org/2.4/index.html ,but cvRect() in the C API is cvRect(x,y,width,height).I think their prototypes maybe the same.)
2.for (int i = 0; i < height; i += 8) and for (int j = 0; j < width; j+= 8) will cause the error ""Unhandled exception at ...".By changing them to for (int i = 0; i < (height/8)*8; i += 8)andfor (int j = 0; j < (width/8)*8; j+= 8),this error will be sovled.
3.#user3743939 If you managed to sovle your problem,please post your solution to help others.
regards

Related

Open cv Error : Assertion failed (IIR filter on video frames)

in below code i want to apply temp_rec filter on movies frame.
But i got the error assertion failed.
with video_line_extractor function extract a time series of pixels in a row
then in the main i apply my temporal filter to all of the row of the image.
I know it is a inefficient native code but i can not use of opencv internal
function instead of my temp_rec function.
int width_frame, heigth_frame, num_frames;
VideoCapture cap;
void temp_rec(float* in, float* out, int w, float tau) {
float yp;
float tauo = 1 / tau;
for (int i = 0; i<w;i++) {
if (i == 0) {
*out = tauo*(*in);
}
else {
out -= 1;
yp = *(out);
out += 1;
*(out) = tauo*(*(in)) + ((exp(-tauo))*yp);
}
out += 1;
in += 1;//prepare for calculate next element
}
}
Mat video_line_extractor(int whichrow) {//extract a row of frames
// Create a VideoCapture object and open the input file
// If the input is the web camera, pass 0 instead of the video file name
cap = VideoCapture("a valid path");
int frame_counter = 0;
Mat M_temp = Mat::eye(width_frame, num_frames, CV_8UC3);
// Check if camera opened successfully
if (!cap.isOpened()) {
cout << "Error opening video stream or file :(" << endl;
}
while (frame_counter<num_frames) {
Mat frame;
// Capture frame-by-frame
cap >> frame;
// If the frame is empty, break immediately
if (frame.empty())
break;
cvtColor(frame, frame, CV_BGR2GRAY);
for(int j=0;j<width_frame;j++) //we in above first extract a movie frame that as we know it is a image
//in this 'for' we extract that row data with a pointer to one of the row in th M_temp
M_temp.at<uchar>(frame_counter , j) = frame.ptr<uchar>(whichrow)[j];
frame_counter++;
}
// When everything done, release the video capture object
cap.release();
return M_temp;
}
int main() {
cap=VideoCapture("a valid path");
width_frame = cap.get(CV_CAP_PROP_FRAME_WIDTH);
heigth_frame = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
num_frames = cap.get(CV_CAP_PROP_FRAME_COUNT);
Mat image= Mat::zeros(width_frame, num_frames, CV_8UC3);//initalize input
Mat image_o = Mat::zeros(width_frame, num_frames, CV_8UC3);//initialize output
for (int jj = 0;jj < heigth_frame;jj++) {
image = video_line_extractor(jj);
for (int j = 0;j < width_frame;j++)
temp_rec((float *)image.ptr<uchar>(j), (float *)image_o.ptr<uchar>(j), num_frames, 10);
}
imshow("Image", image);
waitKey(0);
return 0;
}
edit: assertion error
https://i.stack.imgur.com/BGGu0.png
int width_frame, heigth_frame, num_frames;
VideoCapture cap;
void temp_rec(float* in, float* out, int w, float tau) {
float yp;
float tauo = 1 / tau;
for (int i = 0; i<w;i++) {
if (i == 0) {
*out = tauo*(*in);
}
else {
out -= 1;
yp = *(out);
out += 1;
*(out) = tauo*(*(in)) + ((exp(-tauo))*yp);
}
out += 1;
in += 1;//prepare for calculate next element
}
}
Mat video_line_extractor(int whichrow) {//extract a row of frames
// Create a VideoCapture object and open the input file
// If the input is the web camera, pass 0 instead of the video file name
cap = VideoCapture("a valid path");
int frame_counter = 0;
Mat M_temp = Mat::eye(width_frame, num_frames, CV_8UC3);
// Check if camera opened successfully
if (!cap.isOpened()) {
cout << "Error opening video stream or file :(" << endl;
}
while (frame_counter<num_frames) {
Mat frame;
// Capture frame-by-frame
cap >> frame;
// If the frame is empty, break immediately
if (frame.empty())
break;
cvtColor(frame, frame, CV_BGR2GRAY);
for(int j=0;j<width_frame;j++) //we in above first extract a movie frame that as we know it is a image
//in this 'for' we extract that row data with a pointer to one of the row in th M_temp
M_temp.at<uchar>(frame_counter , j) = frame.ptr<uchar>(whichrow)[j];
frame_counter++;
}
// When everything done, release the video capture object
cap.release();
return M_temp;
}
int main() {
cap=VideoCapture("a valid path");
width_frame = cap.get(CV_CAP_PROP_FRAME_WIDTH);
heigth_frame = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
num_frames = cap.get(CV_CAP_PROP_FRAME_COUNT);
Mat image= Mat::zeros(width_frame, num_frames, CV_8UC3);//initalize input
Mat image_o = Mat::zeros(width_frame, num_frames, CV_32FC3);//initialize output
for (int jj = 0;jj < heigth_frame;jj++) {
image = video_line_extractor(jj);
for (int j = 0;j < width_frame;j++)
temp_rec((float *)image.ptr<uchar>(j), (float *)image_o.ptr<uchar>(j), num_frames, 10);
}
imshow("Image", image);
waitKey(0);
return 0;
}

vector<Mat> opencv issues

I am trying to read images of size 19x19 into vector. I have 2429 number of such images. But when I run my code, I am sure some Mat images are not read into the vector. Is it a memory issue. If yes, can anyone help me. I confirmed this after having assert statements in my code.Thank you for the help. EDIT: I removed all the if else statements and replaced it with format specifier. When I am building the design matrix X_train, exactly at ex = 1703 my assertion fails. I checked my image set around those ex values and they look fine. I am not able to understand where I am going wrong.
#include <iostream>
#include <vector>
#include <istream>
#include <fstream>
#include <random>
#include <algorithm>
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#define NO_OF_IMAGES 2429
using namespace std;
using namespace cv;
static int colSize = 0;
vector<Mat> read_faces() {
vector<Mat> training_images;
string images_path = "images/train/face";
string suffix = ".pgm";
Mat img(19, 19, CV_8UC1);
for (int i = 0; i < NO_OF_IMAGES; i++) {
img = imread( cv::format("%s%05d.pgm", images_path.c_str(), i), 0 );
training_images.push_back(img);
}
return training_images;
}
vector<Mat> extract_train_test_set(
vector<Mat> faces/**< [in] vector of faces or matrices*/,
vector<Mat> &test_set /**< [out] 10% of images*/) {
/**
* Randomly select 90% of these images and collect them into a set training_set and
* the rest 10% in test_set.
*/
int percentage_train = (0.9f * NO_OF_IMAGES);
vector<Mat> training_set;
for (int i = 0; i < percentage_train; i++) {
Mat img = faces[i];
assert(img.empty() == false);
training_set.push_back(img);
}
for (int i = percentage_train; i < NO_OF_IMAGES; i++) {
Mat img = faces[i];
assert(img.empty() == false);
test_set.push_back(img);
}
return training_set;
}
int main(int argc, char **argv) {
vector<Mat> faces = read_faces(); /**< Reading faces into a vector of matrices. */
random_shuffle(faces.begin(), faces.end()); /**< Shuffle the faces vector for creating a training set*/
cout << faces.size() << endl; /**< Size of the vector of faces is 2429*/
vector<Mat> training_set; /**< 90% images i.e 2186 are test images. */
vector<Mat> test_set; /**< 10% images i.e 243 are test images. */
training_set = extract_train_test_set(faces, test_set);
cout << " Training set size " << training_set.size() << endl;
cout << " Test set size " << test_set.size() << endl;
int dim = training_set[0].rows * training_set[0].cols; /**< 361 dimension vector. */
Mat X_train(dim, training_set.size(), CV_8UC1); /**< 361 rows and 2186 columns.*/
Mat m(19, 19, CV_8UC1);
int ex = 0; /**< Counter for indexing the images */
while (ex < training_set.size()) {
m = training_set[ex];/**< Retrieve the image from training vector. */
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
assert(m.empty() == false);
X_train.at<uchar>(colSize, ex) = m.at<uchar>(i, j); //each image is a 361 element vector
colSize++;
}
}
ex++; /**< Continue to next image. */
colSize = 0; /**< Set to zero so as to continue to next image. That is a reset row index for next image.*/
}
ofstream file_handle("images/train.dat", ios::trunc);
file_handle << X_train;
file_handle.close();
cout << "Height " << X_train.rows << " Width " << X_train.cols << endl;
waitKey(0);
return 0;
}
I got it working. Instead of looping across the image in which I manually set 19 rows and 19 cols (given that each image as 19x19), I used that Mat's class members 'rows' and 'cols'. Solution I found is just replacement with the following:
while (ex < training_set.size()) {
m = training_set[ex];/**< Retrieve the image from training vector. */
cout << "Fine!! " << ex << endl;
assert(m.empty() == false);
for (int i = 0; i < m.rows; i++) {
for (int j = 0; j < m.cols; j++) {
X_train.at<uchar>(colSize, ex) = m.at<uchar>(i, j); //each image is a 361 element vector
colSize++;
}
}
ex++; /**< Continue to next image. */
colSize = 0; /**< Set to zero so as to continue to next image. That is a reset row index for next image.*/
}

Embed watermark using dct on image opencv

I wants to embed watermark into an image using dct with c++ and opencv.
I split image into 8x8 block and apply dct to each block.
Now I don't know what to do next, Can anyone give me some hint or help me?
Here is my work so far.
int main() {
Mat originalImage;
originalImage = imread("image.jpg");
if( !originalImage.data )
{
std::cout<< "Error loading original image!"<<std::endl;
return -1;
}
cout << "Working on image from image.jpg" << endl;
/// Create Windows
namedWindow("Original", 1);
imshow( "Original", originalImage );
int x = 0; int y = 0;
moveWindow("Original", x, y);
imshow("Original", originalImage);
x += 100; y += 100;
int width = originalImage.size().width;
int height = originalImage.size().width;
cout << "Original image Width x Height is " << width << "x" << height << endl;
// Leave original alone, work on a copy
Mat dctImage = originalImage.clone();
// Step through the copied image with rectangles size 8x8
// For each block, split into planes, do dct, and merge back
// into the block. (This will affect the image from
// which the block is selected each time.)
for (int i = 0; i < height; i += 8)
{
for (int j = 0; j < width; j+= 8)
{
Mat block = dctImage(Rect(i, j, 8, 8));
vector<Mat> planes;
split(block, planes);
vector<Mat> outplanes(planes.size());
for (size_t k = 0; k < planes.size(); k++)
{
planes[k].convertTo(planes[k], CV_32FC1);
dct(planes[k], outplanes[k]);
outplanes[k].convertTo(outplanes[k], CV_8UC1);
}
merge(outplanes, block);
}
}
namedWindow("dctBlockImage");
moveWindow("dctBlockImage", x, y);
imshow("dctBlockImage", dctImage);
x += 100; y += 100;
waitKey();
destroyAllWindows();
return 0;
}

OpenCV using Mat to modify video pixel value and merging back

Hi really hope someone could help me out with this, been stuck for quite awhile. After the changing the pixel value of blue at x = 100, y = 200 and merging back as fin_vid.
The value doesn't seems to be the same as what I wanted when I read back from the fin_vid.
There is something wrong with my merging but I don't understand why.
split(frame, rgb);
Mat fin_vid, tmp;
namedWindow("blue",1);
imshow("Original Video", frame);
imshow("blue", rgb[0]);
if (waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
rgb[0].convertTo(tmp, CV_8UC1);
for(int j = 0; j<ModText.size(); j++)
{
for(int k = 0; k<8; k++)
{
int blue = (int)tmp.at<uchar>(hx+j,wy+k);
cout<<blue<<endl;
if (blue%2==1)
{
if ( ary[j][k]== 48){
blue = blue - 1;
}
}
else if( ary[j][k] == 49) {
blue = blue + 1;
}
tmp.at<uchar>(hx+j,wy+k)=blue;
cout << "the new value of the pixel is " << (int)(tmp.at<uchar>(hx+j,wy+k)) << endl;}
vector<Mat> channels;
channels.push_back(tmp);
channels.push_back(rgb[1]);
channels.push_back(rgb[2]);
merge(channels, fin_vid);
namedWindow("B",1);imshow("B", fin_vid);
namedWindow("watermarked video");
imshow("watermarked video", fin_vid);
outputVideo.write(fin_vid);
}

Access pixels with Mat OpenCV

I would like to access pixels in RGB with OpenCV 2.3.
I'm trying like this but it's like every pixels are equal frame after frame because I got no output. Images are from my webcam and I can see them.
Btw RED = 0;
THX
Mat frame;
Mat oldFrame;
VideoCapture cap(0);
cap >> oldFrame;
sumFramePix = oldFrame.cols * oldFrame.rows;
nbChannels = oldFrame.channels();
cout << "NbcHANNELs : " << nbChannels << endl;
imshow("Video 1", oldFrame);
while(1)
{
cap >> frame;
imshow("Video 1", frame);
for(int i=0; i<frame.rows; i++)
{
for(int j=0; j<frame.cols; j++)
{
if (frame.ptr<uchar>(i)[nbChannels*j+RED] < oldFrame.ptr<uchar>(i)[nbChannels*j+RED])
{
cout << "==============-";
}
}
}
oldFrame = frame;
if(waitKey(300) >= 0) break;
}
Change
oldFrame = frame;
to
oldFrame = frame.clone();
You are creating two Mat objects that point to the same data. clone() makes a deep copy.