resize matrix with copying the data opencv - opencv

I am trying to create a matrix with only one column from another matrix and of course with copying the data.
void redim( Mat in , Mat &out) {
for (int l=0 ; l < in.rows*in.cols ; l++){
for(int j=0; j< in.rows ; j++){
for(int i=0 ; i < in.cols; i++){
out.at <float> (l,0)= in.at <float> (j,i);
}
}
}
}
int main(){
Mat It3;
It3 = (Mat_<double>(2,3) << 0,4,6,7,8,9);
Mat S= Mat :: zeros ( It3.rows* It3.cols , 1, CV_32FC1) ;
redim(It3,S);
waitKey();
}
But I got as result the matrix S=[0;0;0;0;0;0].

Your are mixing float and double as data type. Choose one!
Your for loops don't make any sense.
You can:
correct your for loop, as in toSingleColumn1
using a for loop, but using indices, as in toSingleColumn2
using cv::reshape, which does exactly this, as in toSingleColumn3
See the code below. b1, b2 and b3 will be equal:
#include <opencv2\opencv.hpp>
using namespace cv;
// Use two for loops, with coordinates
void toSingleColumn1(const Mat1f& src, Mat1f& dst)
{
int N = src.rows * src.cols;
dst = Mat1f(N, 1);
int i=0;
for (int r = 0; r < src.rows; ++r) {
for (int c = 0; c < src.cols; ++c) {
dst(i++, 0) = src(r, c);
}
}
}
// Use a single for loop, with indices
void toSingleColumn2(const Mat1f& src, Mat1f& dst)
{
int N = src.rows * src.cols;
dst = Mat1f(N, 1);
for (int i = 0; i < N; ++i) {
dst(i) = src(i);
}
}
// Use cv::reshape
void toSingleColumn3(const Mat& src, Mat& dst)
{
// The 'clone()' is needed to deep copy the data
dst = src.reshape(src.channels(), src.rows*src.cols).clone();
}
int main()
{
Mat1f a = (Mat1f(2,3) << 0.f, 4.f, 6.f, 7.f, 8.f, 9.f);
Mat1f b1, b2, b3;
toSingleColumn1(a, b1);
toSingleColumn2(a, b2);
toSingleColumn3(a, b3);
return 0;
}

Related

What's a c++ code difference between contrast stretch of RGB and grayscale images?

I'm trying grayscale contrast stretching with c++ program, so a source I follow for that is here. There is a code I've got so far:
#include<iostream>
#include<opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
int computeStretched(int x, int l1, int l2, int r1, int r2);
int main() {
Mat img = imread("pict6.jpg"); // Mat type initialization of an original image
Mat grayScaleImg(img.size(), CV_8UC1);; // Gray scale mat initialization
cvtColor(img, grayScaleImg, COLOR_BGR2GRAY); // conversion of image input to grayscaled view
for (int i = 0; i < img.rows; i++) {
for (int j = 0; j < img.cols; j++) {
for (int k = 0; k < 3; k++) {
int output = computeStretched(grayScaleImg.at<Vec3b>(i, j)[k], 70, 0, 200, 255);
stretch_result.at<Vec3b>(i, j) = saturate_cast<uchar>(output);
}
}
}
waitKey(0);
return 0;
}
int computeStretched(int x, int l1, int l2, int r1, int r2) {
float calcVal;
if (0 <= x && x <= l1) {
calcVal = (l2 / l1) * x;
}else if (l1 < x && x <= r1) {
calcVal = ((r2 - l2) / (r1 - l1)) * (x - l1) + l2;
}else if (r1 < x && x <= 255) {
calcVal = ((255 - r2)/(255 - r1)) * (x - r1) + r2;
}
return (int)calcVal;
}
Hovewer, the image I put to processing isn't RGB-converted, but grayscale one. I want to do same operation as in the sample code using plainly grayscale picture too. What must be changed in the listing above to enable that?
You have GrayScale image that means 1 channel.
so modify your code accordingly :
for (int i = 0; i < img.rows; i++) {
for (int j = 0; j < img.cols; j++) {
int output = computeStretched(grayScaleImg.at<uchar>(i, j), 70, 0, 200, 255);
stretch_result.at<uchar>(i, j) = saturate_cast<uchar>(output);
}
}
Initlize "stretch_result

Opencv Mat efficiency linearized by right triangle

How to efficiency linearized Mat (symmetric matrix) to one row by right triangle.
For example, when I have:
0aabbb
b0aaaa
ba0bba
bac0aa
aaaa0c
abcab0
and then from that I get:
aabbbaaaabbaaac
Something like this:
...
template<class T>
Mat SSMJ::triangleLinearized(Mat mat){
int c = mat.cols;
Mat row = Mat(1, ((c*c)-c)/2, mat.type());
int i = 0;
for(int y = 1; y < mat.rows; y++)
for(int x = y; x < mat.cols; x++) {
row.at<T>(i)=mat.at<T>(y, x);
i++;
}
return row;
}
...
Since data in your mat is just a 1d array stored in row.data you can do whatever you want with it. I don't think you will find anything more special (w/o using vectorized methods) than just copying from this array.
int rows = 6;
char data[] = { 0,1,2,3,4,5,
0,1,2,3,4,5,
0,1,2,3,4,5,
0,1,2,3,4,5,
0,1,2,3,4,5};
char result[100];
int offset = 0;
for (int i = 0; i < 5; offset += 5-i, i++) {
memcpy(&result[offset] , &data[rows * i + i + 1], 5 - i);
}
Or with opencv Mat it would be
int rows = mat.cols;
char result[100]; // you can calculate how much data u need
int offset = 0;
for (int i = 0; i < 5; offset += 5-i, i++) {
memcpy(&result[offset] , &mat.data[rows * i + i + 1], 5 - i);
}
Mat resultMat(1, offset, result);

Opencv - polynomial function fitting

In opencv (or other c++ lib), is there a similar function like matlab fit which can do 3d polynomial surface fitting (i.e. f(x,y)= p00 + p10*x + p01*y + p20*x^2 + p11*x*y + p02*y^2). Thanks
I don't think there is a lib in opencv but you can do like that :
int main( int argc, char** argv )
{
Mat z = imread("1449862093156643.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat M = Mat_<double>(z.rows*z.cols,6);
Mat I=Mat_<double>(z.rows*z.cols,1);
for (int i=0;i<z.rows;i++)
for (int j = 0; j < z.cols; j++)
{
double x=(j - z.cols / 2) / double(z.cols),y= (i - z.rows / 2) / double(z.rows);
M.at<double>(i*z.cols+j, 0) = x*x;
M.at<double>(i*z.cols+j, 1) = y*y;
M.at<double>(i*z.cols+j, 2) = x*y;
M.at<double>(i*z.cols+j, 3) = x;
M.at<double>(i*z.cols+j, 4) = y;
M.at<double>(i*z.cols+j, 5) = 1;
I.at<double>(i*z.cols+j, 0) = z.at<uchar>(i,j);
}
SVD s(M);
Mat q;
s.backSubst(I,q);
cout<<q;
imshow("Orignal",z);
cout<<q.at<double>(2,0);
Mat background(z.rows,z.cols,CV_8UC1);
for (int i=0;i<z.rows;i++)
for (int j = 0; j < z.cols; j++)
{
double x=(j - z.cols / 2) / double(z.cols),y= (i - z.rows / 2) / double(z.rows);
double quad=q.at<double>(0,0)*x*x+q.at<double>(1,0)*y*y+q.at<double>(2,0)*x*y;
quad+=q.at<double>(3,0)*x+q.at<double>(4,0)*y+q.at<double>(5,0);
background.at<uchar>(i,j) = saturate_cast<uchar>(quad);
}
imshow("Simulated background",background);
waitKey();
return 0;
}
Original post is here
There is an undocumented function in openCV (contrib.hpp) called cv::polyfit(). It takes as input a Mat of x coordinates and another Mat of y coordinates. Not very easy to use Mats for this but you can build a wrapper for sending a vector of cv::Point points.
vector <float> fitPoly(const vector <Point> &src, int order){
Mat src_x = Mat(src.size(), 1, CV_32F);
Mat src_y = Mat(src.size(), 1, CV_32F);
for (int i = 0; i < src.size(); i++){
src_x.at<float>(i, 0) = (float)src[i].x;
src_y.at<float>(i, 0) = (float)src[i].y;
}
return cv::polyfit(src_x, src_y, order);
}

error in runing source face detection in opencv 2.4.9 and vs 2012

i use pre-build opencv 2.4.9 i test the image show in opencv 2.4.9 it works,but for this source its have error?! if this errors is that i use pre-build opencv?what to do what not to do
i copy the xml file in current folder and my hardware corei5,Radeon ATI graphic
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <opencv/ml.h>
void doMosaic(IplImage* in, int x, int y,
int width, int height, int size);
int main (int argc, char **argv)
{
int i, c;
IplImage *src_img = 0, *src_gray = 0;
const char *cascade_name = "haarcascade_frontalface_alt.xml";
CvHaarClassifierCascade *cascade = 0;
CvMemStorage *storage = 0;
CvSeq *faces;
cascade = (CvHaarClassifierCascade *) cvLoad (cascade_name, 0, 0, 0);
cvNamedWindow ("Capture", CV_WINDOW_AUTOSIZE);
CvCapture *capture = cvCreateCameraCapture(0);
assert(capture != NULL);
while (1) {
src_img = cvQueryFrame (capture);
src_gray = cvCreateImage (cvGetSize(src_img), IPL_DEPTH_8U, 1);
storage = cvCreateMemStorage (0);
cvClearMemStorage (storage);
cvCvtColor (src_img, src_gray, CV_BGR2GRAY);
cvEqualizeHist (src_gray, src_gray);
faces = cvHaarDetectObjects (src_gray, cascade, storage,
1.11, 4, 0, cvSize (40, 40));
for (i = 0; i < (faces ? faces->total : 0); i++) {
CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
doMosaic(src_img, r->x, r->y, r->width, r->height, 20);
}
cvShowImage("Capture", src_img);
cvReleaseImage(&src_gray);
c = cvWaitKey (2);
if (c == '\x1b')
break;
}
cvReleaseCapture (&capture);
cvDestroyWindow ("Capture");
return 0;
}
void doMosaic(IplImage* in, int x0, int y0,
int width, int height, int size)
{
int b, g, r, col, row;
int xMin = size*(int)floor((double)x0/size);
int yMin = size*(int)floor((double)y0/size);
int xMax = size*(int)ceil((double)(x0+width)/size);
int yMax = size*(int)ceil((double)(y0+height)/size);
for(int y=yMin; y<yMax; y+=size){
for(int x=xMin; x<xMax; x+=size){
b = g = r = 0;
for(int i=0; i<size; i++){
if( y+i > in->height ){
break;
}
row = i;
for(int j=0; j<size; j++){
if( x+j > in->width ){
break;
}
b += (unsigned char)in->imageData[in->widthStep*(y+i)+(x+j)*3];
g += (unsigned char)in->imageData[in->widthStep*(y+i)+(x+j)*3+1];
r += (unsigned char)in->imageData[in->widthStep*(y+i)+(x+j)*3+2];
col = j;
}
}
row++;
col++;
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
in->imageData[in->widthStep*(y+i)+(x+j)*3] = cvRound((double)b/(row*col));
in->imageData[in->widthStep*(y+i)+(x+j)*3+1] = cvRound((double)g/(row*col));
in->imageData[in->widthStep*(y+i)+(x+j)*3+2] = cvRound((double)r/(row*col));
}
}
}
}
}
the error is a break in microsoft ,please help me.thanks very much
First-chance exception at 0x75C4B727 in opencv.exe: Microsoft C++ exception: cv::Exception at memory location 0x003CF678.
If there is a handler for this exception, the program may be safely continued.
finally i succeed,i first for PDB errors tools>option>debugging>outputwindow>moduleloadmessage >off and then i tools>option>debugging>symbols>microsoft symbols server not checked and then i chnge capture.open( -1 ); to capture.open( 0 ); now by seting in opencv itworks,thanks very much

Openni opencv kinect Bad Memory allocation

Basically I've got a loop which goes through all the kinects depth pixels. If they are greater than 3000mm it sets the pixel value to black.
For some reason this works only at a close range while pointed to a wall. If I pull the kinect back (giving it a larger area to scan) I get a Bad Memory allocation error. My code can be found below. I get the bad memory allocation error inside that try catch statement. Most of the code is from the opencv kinect sample here and here.
i figured out the problem, its because the depth values are stored in an array instead of matrix, i need a better way of finding out which location in the array, the x.y of the pixels which start from 1,1 point to instead of the (i = x+y*640)
#include <opencv.hpp>
#include <iostream>
#include <string>
#include <stdio.h>
#include <OpenNI.h>
using namespace std;
using namespace cv;
int main()
{
openni::Device device;
openni::VideoStream depth;
const char* device_uri = openni::ANY_DEVICE;
openni::Status ret = openni::OpenNI::initialize();
// Open
ret =device.open( device_uri );
ret = depth.create( device, openni::SENSOR_DEPTH );
if ( ret == openni::STATUS_OK )
{
// Start Depth
depth.start();
}
// Get Depth Stream Min-Max Value
int minDepthValue = depth.getMinPixelValue();
int maxDepthValue = depth.getMaxPixelValue();
//cout << "Depth min-Max Value : " << minDepthValue << "-" << maxDepthValue << endl;
// Frame Information Reference
openni::VideoFrameRef depthFrame;
// Get Sensor Resolution Information
int dImgWidth = depth.getVideoMode().getResolutionX();
int dImgHeight = depth.getVideoMode().getResolutionY();
// Depth Image Matrix
cv::Mat dImg = cv::Mat( dImgHeight, dImgWidth, CV_8UC3 );
Mat grey= cvCreateImage(cvSize(640, 480), 8, 1); ;
for(;;)
{
depth.readFrame( &depthFrame );
openni::DepthPixel* depthImgRaw = (openni::DepthPixel*)depthFrame.getData();
for ( int i = 0 ; i < ( depthFrame.getDataSize() / sizeof( openni::DepthPixel ) ) ; i++ )
{
int idx = i * 3; // Grayscale
unsigned char* data = &dImg.data[idx];
int gray_scale = ( ( depthImgRaw[i] * 255 ) / ( maxDepthValue - minDepthValue ) );
data[0] = (unsigned char)~gray_scale;
data[1] = (unsigned char)~gray_scale;
data[2] = (unsigned char)~gray_scale;
}
openni::DepthPixel* depthpixels = (openni::DepthPixel*)depthFrame.getData();
cvtColor(dImg, grey, CV_RGB2GRAY);
int i ;
try{
for( int y =0; y < 480 ; y++){
//getting in to each pixel in a row
for(int x = 0; x < 640; x++){
//getting out the corresponding pixel value from the array
i = x+y*640;
if (depthpixels[i] >3000)
{
grey.at<unsigned char>(x,y) = 0;
}
}
}
}catch(exception e)
{cout << e.what() <<endl ;
cout <<depthpixels[i] <<endl ;
cout << i <<endl ;
}
// cv:imshow( "depth", dImg );
imshow("dpeth2", grey);
int k = cvWaitKey( 30 ); // About 30fps
if ( k == 0x1b )
break;
}
// Destroy Streams
depth.destroy();
// Close Device
device.close();
// Shutdown OpenNI
openni::OpenNI::shutdown();
return 0;
}
solved the problem simply by swapping my x and y around
for( y =0; y < 480 ; y++)
{
//getting in to each pixel in a row
for( x = 0; x < 640; x++)
{
if (depthpixels[i]>1500)
{
grey.at<unsigned char >(y,x) = 0;
}
if (depthpixels[i] <500)
{
grey.at<unsigned char >(y,x) = 0;
}
i++;
}
}

Resources