OpenCV using Mat to modify video pixel value and merging back - mat

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);
}

Related

Extraction of each HSV value from an image using OpenCV and C++

I used the code below to extract each HSV value from any image and to print each value on the screen.
Mat image_HSV;
cvtColor(ori_image, image_HSV, CV_BGR2HSV);
Mat mask;
inRange(image_HSV, Scalar(100, 0, 0), Scalar(100, 255, 255), mask);
image_HSV.setTo(Scalar(0, 0, 0), mask);
int h = 0;
int s = 0;
int v = 0;
int col = image_HSV.cols;
int row = image_HSV.rows;
int corow = col * row; // image's full pixel number
for (int i = 0; i < image_HSV.cols; i++) { // image row pixel
for (int j = 0; j < image_HSV.rows; j++) { // image col pixel
Vec3b hsv = image_HSV.at<Vec3b>(i,j);
h += hsv.val[0];
s += hsv.val[1];
v += hsv.val[2];
if (hsv[0] != 100) {
hsv[0] = 0;
hsv[1] = 0;
hsv[2] = 0;
}
}
}
cout << "H: " << h / corow << "% \n";
cout << "S: " << s / corow << "% \n";
cout << "V: " << v / corow << "% \n";
waitKey(0);
return 0;
I used all red color image for this time, which RGB values were 255, 0, 0.
However, I have some strange results from this code.
As I know, each H,S,V value range is covered by 0-360, 0-100, and 0-100, respectively.
Further, I also followed the post linked below but I still have a trouble to get right values.
OpenCV (C++) - Set HSV values of a pixel
But, I still don't know how to fix it.
Any help would be greatly appreciated! Thanks!

OpenCV fisheye undistort issues

EDIT: I found the cause of the problem, the fisheye::undistortImage() function was not working correctly, I replaced it with estimateNewCameraMatrixForUndistortRectify(), initUndistortRectifyMap(), and remap() as in the original calibrate camera example. Not perfect yet but going in the right direction. Output image: http://imgur.com/a/Xm5vq
Mat output;
Mat newK;
Mat view, map1, map2;
Size newSize(1200, 1200);
Mat rview(newSize, frame.type());
//resize(rview, rview, newSize);
fisheye::estimateNewCameraMatrixForUndistortRectify(K, D, frame.size(), Matx33d::eye(), newK, 1);
fisheye::initUndistortRectifyMap(K, D, Matx33d::eye(), newK, frame.size(), CV_16SC2, map1, map2);
//fisheye::undistortImage(frame, output, K, D, identity);
remap(frame, rview, map1, map2, INTER_LINEAR);
imshow("Image View", rview);
imshow(window_name, frame);
if (waitKey(50) == 27) {
break;
}
Original post:
I'm trying to calibrate and undistort an image coming from an 180 degree fisheye USB camera. Most of this code is from existing examples that claim to be functional.
The code runs fine until fisheye::undistortImage where the output image is very distorted and centered around the top left corner of the window.
Screen shot of the "undistorted" chess board and calibration matrix outputs -
http://imgur.com/a/RTIoT
What am I missing here?
int main(int argc, char** argv) {
VideoCapture camera;
camera.open(1);
if (!camera.isOpened()) {
cout << "Failed to open camera." << std::endl;
return -1;
}
double fWidth = camera.get(CAP_PROP_FRAME_WIDTH);
double fHeight = camera.get(CAP_PROP_FRAME_HEIGHT);
cout << fWidth << std::endl;
cout << fHeight << std::endl;
/*
640 320
480 240
*/
const char* window_name = "output";
namedWindow(window_name, WINDOW_NORMAL);
Mat frame;
Size boardSize;
boardSize.width = 9;
boardSize.height = 6;
int remaining_frames = 30;
Mat K;// = Mat(3, 3, CV_64F, vK);
Mat D;
Mat identity = Mat::eye(3, 3, CV_64F);
vector<vector<Point2f> > img_points;
vector<vector<Point3f> > obj_points(1);
int sq_sz = 25;
for (int i = 0; i < boardSize.height; i++) {
for (int j = 0; j < boardSize.width; j++) {
obj_points[0].push_back(Point3f(float(j * sq_sz), float(i * sq_sz), 0));
}
}
obj_points.resize(remaining_frames, obj_points[0]);
bool found = false;
clock_t prevTimestamp = 0;
int delay = 500;
while (1) {
frame = nextFrame(camera);
bool blinkOutput = false;
if (remaining_frames > 0) {
vector<Point2f> corners;
int chessBoardFlags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE;
found = findChessboardCorners(frame, boardSize, corners, chessBoardFlags);
if (found) {
drawChessboardCorners(frame, boardSize, corners, found);
if (clock() - prevTimestamp > delay*1e-3*CLOCKS_PER_SEC) {
Mat viewGray;
cvtColor(frame, viewGray, COLOR_BGR2GRAY);
cornerSubPix(viewGray, corners, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.1));
img_points.push_back(corners);
remaining_frames--;
cout << remaining_frames << " frames to calibration." << endl;
blinkOutput = true;
prevTimestamp = clock();
}
if (remaining_frames == 0) {
cout << "Computing distortion" << endl;
int flags = 0;
flags |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
flags |= cv::fisheye::CALIB_CHECK_COND;
flags |= cv::fisheye::CALIB_FIX_SKEW;
fisheye::calibrate(obj_points, img_points, frame.size(), K, D, noArray(), noArray(), flags);
cout << "Finished computing distortion" << endl;
cout << K << endl;
cout << D << endl;
}
}
if (blinkOutput) { bitwise_not(frame, frame); }
cv::imshow(window_name, frame);
if (waitKey(50) == 27) {
break;
}
}
else {
Mat output;
fisheye::undistortImage(frame, output, K, D, identity);
cv::imshow(window_name, output);
if (waitKey(50) == 27) {
break;
}
}
}
return 0;
}

Split image frame into 8*8 for DCT using OpenCV and 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

Video gets stuck meanshift tracking opencv

I want to track any moving object using meanshift algorithm. For this I am first subtracting frames from background. Then erosion, dilation and smoothing is applied. In order to detect moving object, and to find its coordinates, I am using corner point detection.
Then I calculate mean of corner points, and pass these points to meanshift searching window. Now when object appears in screen, the program leaves corner point detection and enters meanshift tracking. It keeps running in meanshift until the object leaves the screen.
Now if object leaves the screen, I want to activate corner point detection again. For this, I take the program out of meanshift and jump back to corner point detection. The program is running fine but the problem is when it leaves meanshift and enters corner point detection again, it gets stuck for few seconds.
After that it runs smoothly. The problem occurs only during transition from meanshift to corner point detection. I don't know what could be the possible reason. Kindly tell me some solution.
Here is my code:
#include "highgui.h"
#include "cv.h"
#include "cxcore.h"
#include "cvaux.h"
#include <iostream>
using namespace std;
const int MAX_CORNERS = 500;
inline static void allocateOnDemand(IplImage** img, CvSize size, int depth, int channels) {
if (*img != NULL)
return;
*img = cvCreateImage(size, depth, channels);
if (*img == NULL) {
fprintf(stderr, "Error: Couldn't allocate image. Out of memory?\n");
exit(-1);
}
}
int main() {
CvCapture* capture = cvCaptureFromCAM(CV_CAP_V4L2);
IplImage* pFrame[10];
IplImage* bg;
IplImage* img_A;
IplImage* img_B;
IplImage* eig_image;
IplImage* tmp_image;
img_A = cvQueryFrame(capture);
CvSize img_sz = cvGetSize(img_A);
int c1 = 0, c2 = 0;
int xarr[40];
//A temporary replacement for background averaging
int j = 0;
for (j = 0; j < 10; j++) {
pFrame[j] = cvQueryFrame(capture);
cvWaitKey(200);
}
cvSaveImage("10.jpg", pFrame[9], 0); //saving the background
IplImage* imgA = cvCreateImage(cvGetSize(img_A), 8, 1);
IplImage* imgB = cvCreateImage(cvGetSize(img_A), 8, 1);
IplImage* imgB1 = cvCreateImage(cvGetSize(img_A), 8, 1);
IplImage* imgb = cvCreateImage(cvGetSize(img_A), 8, 1);
cvNamedWindow("LKpyr_OpticalFlow", CV_WINDOW_AUTOSIZE);
bg = cvLoadImage("10.jpg", CV_LOAD_IMAGE_GRAYSCALE); //loading the saved background
int flag = 0;
int index = 0;
char keypress;
bool quit = false;
CvConnectedComp*out = new CvConnectedComp(); //output window for meanshift
int win_size = 25; //window size for corner point detection
int x1 = 0;
int y1 = 0;
int x;
int y;
int cc;
line3:
while (quit == false) { //line3:
IplImage* imgC = cvCreateImage(cvGetSize(img_A), 8, 1); //creating output image
cvZero(imgC);
img_B = cvQueryFrame(capture);
imgC = cvQueryFrame(capture);
// line3:
int corner_count = MAX_CORNERS; //total no of corners found in frame
cvCvtColor(img_B, imgb, CV_BGR2GRAY);
//line3:
CvPoint2D32f* cornersA = new CvPoint2D32f[MAX_CORNERS];
CvPoint2D32f* cornersB = new CvPoint2D32f[MAX_CORNERS];
if (index % 2 == 0) {
cvSub(imgb, bg, imgB, NULL); //background subtraction and stuff
cvErode(imgB, imgB, NULL, 4);
cvDilate(imgB, imgB, 0, 2);
cvSmooth(imgB, imgB, 0, 1);
cvThreshold(imgB, imgB, 50, 255, CV_THRESH_BINARY);
//line3:
if (flag == 1) goto line1; //Go to Meanshift
allocateOnDemand(&eig_image, img_sz, IPL_DEPTH_32F, 1);
allocateOnDemand(&tmp_image, img_sz, IPL_DEPTH_32F, 1);
cvCvtColor(img_A, imgA, CV_BGR2GRAY);
//line3:
cvGoodFeaturesToTrack(imgB, eig_image, tmp_image, cornersA, &
corner_count, 0.05, 5.0, 0, 3, 0, 0.04); //detects corners and no of corners stored in corner_count
cvFindCornerSubPix(imgB, cornersA, corner_count, cvSize(12, 12),
cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_ITER |
CV_TERMCRIT_EPS, 20, 0.03));
CvPoint p0;
CvPoint p1;
CvPoint acc;
cc = corner_count + 20;
acc.x = 0;
acc.y = 0;
for (int i = 0; i < corner_count; i++) {
p0 = cvPoint(cvRound(cornersA[i].x), cvRound(cornersA[i].y));
p1 = cvPoint(cvRound(cornersB[i].x), cvRound(cornersB[i].y));
acc.x = acc.x + p0.x; //calculating mean of corner points
acc.y = acc.y + p0.y;
}
delete[] cornersA;
delete[] cornersB;
cout << "Corner Count is" << corner_count << endl;
cout << "Flag status: " << flag << endl;
if (corner_count > 0) {
flag = 1;
cvWaitKey(20);
}
x1 = cvRound(acc.x / (corner_count + 1));
y1 = cvRound(acc.y / (corner_count + 1));
cout << "x is " << x1 << " y is " << y1 << endl;
cout << "Flag status: " << flag << endl;
x = x1;
y = y1;
if (flag == 0) goto line2; //Go back to Corner Point detection
line1: CvRect window = cvRect(x, y, 80, 90); //Creates window for meanshift algo
cvMeanShift(imgB, window, cvTermCriteria(CV_TERMCRIT_EPS |
CV_TERMCRIT_ITER, 200, 1), out);
window = out->rect;
x = out->rect.x;
y = out->rect.y;
cout << "Now x is " << x << " y is " << y << endl;
cout << "Flag status: " << flag << endl;
if (out->area > 200) {
cvRectangle(imgC, cvPoint(x + 50, y + 100), cvPoint(x - 20, y -
90), cvScalar(0, 0, 255), 3, 8, 0);
} else {}
xarr[c1] = x;
c1++;
if (c1 > 39) c1 = 0;
if (xarr[0] == xarr[39]) {
c2 = 1;
cout << "c2 is now " << c2 << endl;
}
}
if (x == 0 || y == 0 || x < 7 || x > 572 || c2 == 1) {
flag = 0;
c2 = 0;
goto line3;
break;
}
line2: cvShowImage("LKpyr_OpticalFlow", imgC);
keypress = cvWaitKey(20);
// Set the flag to quit if escape was pressed
if (keypress == 27) {
quit = true;
}
//index++;
} //end of while
return 0;
}

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.