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
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;
}
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.*/
}
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;
}
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);
}
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.