The question i have to do is as follows.
Write a program that outputs a histogram of student grades for an assignment. The program should input each student's grades as an integer and stored in a vector. Grades should be entered until the user enters -1 for a grade. the program should then scan through the vector and compute the histogram, the minimum value of a grade is 0 but your program should determine the maximum value entered by the user. use a dynamic array to store the histogram. output the histogram to the console.
with an example added:
input
20
30
4
20
30
30
-1
output
number of 4's: 1
number of 20's: 2
number of 30's: 3
what i have coded thus far is the following:
#include <iostream>
#include <vector>
using namespace std;
void histogram(vector<int> input);
int main()
{
int i=0;
int value;
vector<int> grades;
while(i>=0)
{
cout<<"Enter a grade for the student: ";
cin>>value;
grades.push_back(value);
if((grades[i])==(-1))
{
break;
}
i++;
}
histogram(grades);
}
void histogram(vector<int> input)
{
}
I did try something for the histogram function but it failed in a horrible manner. I have no idea how to approach this histogram thing.
Don't know if this is correct, but I did this.
void histogram(vector<int> input)
{
// declaration of a new array
int aGrades[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
for (std::vector<int>::iterator it = input.begin() ; it != input.end(); ++it)
{
int number = *it;
//cout << number << endl;
aGrades[number] += 1;
//int *it; //works fine
}
for (int gradeLoop = 0; gradeLoop < 100; gradeLoop++)
{
if(aGrades[gradeLoop] > 0 )
{
cout << "Number of " << gradeLoop << "'s: " << aGrades[gradeLoop] << endl;
}
}
}
Related
I am trying to use Eigen unsupported FFT library using FFTW backend. Specifically I am want to do a 2D FFT. Here's my code :
void fft2(Eigen::MatrixXf * matIn,Eigen::MatrixXcf * matOut)
{
const int nRows = matIn->rows();
const int nCols = matIn->cols();
Eigen::FFT< float > fft;
for (int k = 0; k < nRows; ++k) {
Eigen::VectorXcf tmpOut(nRows);
fft.fwd(tmpOut, matIn->row(k));
matOut->row(k) = tmpOut;
}
for (int k = 0; k < nCols; ++k) {
Eigen::VectorXcf tmpOut(nCols);
fft.fwd(tmpOut, matOut->col(k));
matOut->col(k) = tmpOut;
}
}
I have 2 problems :
First, I get a segmentation fault when using this code on some matrix. This error doesn't happen for all matrixes. I guess it's related to an alignment error. I use the functions in the following way :
Eigen::MatrixXcf matFFT(mat.rows(),mat.cols());
fft2(&matFloat,&matFFT);
where mat can be any matrix. Funnily, the code plants only when I compute the FFT over the 2nd dimension, never on the first one. This doesn't happen with kissFFT backend.
Second I don't get the same result as Matlab (that uses FFTW), when the function works. Eg :
Input Matrix :
[2, 1, 2]
[3, 2, 1]
[1, 2, 3]
Eigen gives :
[ (0,5), (0.5,0.86603), (0,0.5)]
[ (-4.3301,-2.5), (-1,-1.7321), (0.31699,-1.549)]
[ (-1.5,-0.86603), (2,3.4641), (2,3.4641)]
Matlab gives :
17 + 0i 0.5 + 0.86603i 0.5 - 0.86603i
-1 + 0i -1 - 1.7321i 2 - 3.4641i
-1 + 0i 2 + 3.4641i -1 + 1.7321i
Only the central part is the same.
Any help would be welcome.
I failed to activate EIGEN_FFTW_DEFAULT in my first solution, activating it reveals an error in the fftw-support implementation of Eigen. The following works:
#define EIGEN_FFTW_DEFAULT
#include <iostream>
#include <unsupported/Eigen/FFT>
int main(int argc, char *argv[])
{
Eigen::MatrixXf A(3,3);
A << 2,1,2, 3,2,1, 1,2,3;
const int nRows = A.rows();
const int nCols = A.cols();
std::cout << A << "\n\n";
Eigen::MatrixXcf B(3,3);
Eigen::FFT< float > fft;
for (int k = 0; k < nRows; ++k) {
Eigen::VectorXcf tmpOut(nRows);
fft.fwd(tmpOut, A.row(k));
B.row(k) = tmpOut;
}
std::cout << B << "\n\n";
Eigen::FFT< float > fft2; // Workaround: Using the same FFT object for a real and a complex FFT seems not to work with FFTW
for (int k = 0; k < nCols; ++k) {
Eigen::VectorXcf tmpOut(nCols);
fft2.fwd(tmpOut, B.col(k));
B.col(k) = tmpOut;
}
std::cout << B << '\n';
}
I get this output:
2 1 2
3 2 1
1 2 3
(17,0) (0.5,0.866025) (0.5,-0.866025)
(-1,0) (-1,-1.73205) (2,-3.4641)
(-1,0) (2,3.4641) (-1,1.73205)
Which is the same as your Matlab result.
N.B.: FFTW seems to support 2D real->complex FFT natively (without using individual FFTs). This is likely more efficient.
fftwf_plan fftwf_plan_dft_r2c_2d(int n0, int n1,
float *in, fftwf_complex *out, unsigned flags);
I have a question about reading MNIST dataset. I got the idea of how the MNIST dataset is constructed. However, I have no clue, how does it read through a following code. Some of you may think that the result of couts are obvious( I wrote values as a comment). But for me it doesn't make sense because it uses the same exact function four times with the same input, but it gets the different output every time.. How does it possible? Please let me know If there is any ambiguity in my question.
Thank you.
Code start:
typedef unsigned char BYTE;
int main()
{
...
FILE *fp = fopen("MNIST/train-images.idx3-ubyte", "rb");
// delcare function;
int magicNumber = readFlippedInteger(fp);
int numImages = readFlippedInteger(fp);
int numRows = readFlippedInteger(fp);
int numCols = readFlippedInteger(fp);
cout << magicNumber << endl; // 2051
cout << numImages << endl; // 60000
cout << numRows << endl; // 28
cout << numCols << endl; // 28
...
}
int readFlippedInteger(FILE *fp)
{
int ret = 0;
BYTE *temp;
temp = (BYTE*)(&ret);
fread(&temp[3], sizeof(BYTE), 1, fp);
fread(&temp[2], sizeof(BYTE), 1, fp);
fread(&temp[1], sizeof(BYTE), 1, fp);
fread(&temp[0], sizeof(BYTE), 1, fp);
return ret;
}
Please don't mix C and C++ unless it is absolutely necessary. The underlying confusion is that the call to fread "moves" the file pointer through the file for you. As #RetiredNinja noted, you are advancing the file pointer 4 bytes at a time. That's how it "knows" how to read the next value even though you didn't tell it to explicitly. You can read all about file pointers here.
An implementation using slightly more idiomatic C++ could be
#include <fstream>
#include <iostream>
#include <algorithm>
int readFlippedInteger(std::istream &in) {
char temp[sizeof(int)];
in.read(temp, sizeof(int));
std::reverse(temp, temp+sizeof(int));
return *reinterpret_cast<int*>(temp);
}
int main() {
std::ifstream fin("MNIST/train-images.idx3-ubyte", std::ios::binary);
if (!fin) {
std::cerr << "Could not open file\n";
return -1;
}
// delcare function;
int magicNumber = readFlippedInteger(fin);
int numImages = readFlippedInteger(fin);
int numRows = readFlippedInteger(fin);
int numCols = readFlippedInteger(fin);
std::cout << magicNumber << std::endl // 2051
<< numImages << std::endl // 60000
<< numRows << std::endl // 28
<< numCols << std::endl; // 28
}
An implementation that uses a user-defined stream manipulator is left as an exercise for the reader.
I want to make the printf function print from right to left because this program convert the value of number to binary and I want it to be printed in proper form for example if I convert 16 it is written like that 00001 but it must look like that 10000 so does anyone know how to do that thanks in advance
#include <stdio.h>
#include <stdlib.h>
int main()
{
int x,rem;
printf("please enter number: ");
scanf("%d",&x);
while (x !=0)
{
rem=x%2;
if (rem==0)
{
printf("0");
}
else
{
printf("1");
}
x = x/2;
rem = 0;
}
return 0;
}
Here it is:
void print_binary(int x)
{
int skip = 1;
unsigned int mask = 1 << 31;
while(mask > 0){
if(x & mask){
skip = 0;
printf("1");
}else{
if(!skip) printf("0");
}
mask >>= 1;
}
printf("\n");
}
This will print the binary number without trailing zeroes.
If you rather want the result to be stored in a string, you can use:
#include <string.h>
void int_to_binary(int x, char * buff) // buff size must be >= 32 !
{
buff[0] = '\0'; // ensure string ends with \0
unsigned int mask = 1 << 31;
for (; mask > 0; mask >>= 1)
{
strcat(buff, (x & mask) ? "1" : "0");
}
}
To check both codes, use:
int main(int argc, char* argv[])
{
int x;
printf("please enter number: ");
scanf("%d",&x);
char bin[32];
int_to_binary(x, bin);
printf("%s\n", bin);
print_binary(x);
}
What we do is using a mask, which in binary is one "1" beginning on the far left and moving one step right at each loop. The "&" is a bite-wise operator (I let you google it to know how it works). If you need more explanation, feel free to ask.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int binary[20];
int q,i=0;
printf("Enter the decimal no\n");
scanf("%d",&q);
while(q > 0)
{
binary[i]=q%2;
i++;
q=q/2;
}
for(int j=i-1;j>=0;j--)
{
printf("%d",binary[j]);
}
return 0;
}
I have a trivial problem but I don't know how to solve it. I just wanna do a simple "foreach" of a Mat to view rgb values. I have next code:
for(int i=0; i<mat.rows; i++)
{
for(int j=0; j<mat.cols; j++)
{
int value_rgb = mat.at<uchar>(i,j);
cout << "(" << i << "," << j << ") : " << value_rgb <<endl;
}
}
The mat is 200 rows x 200 cols. When I print on console the results, just in the final the programs fails with next error:
**OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 <(unsigned)size.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3) - 1))*4) & 1 5) == elemSize1()) in unknown function, file c:\opencv\build\include\opencv2\core\mat.hpp, line 537**
Anyone can help me?
Thanks.
The below piece of code will help you in accessing the rgb pixel values.You have to access three channels to view RGB values.
for(int i = 0; i < i<mat.rows; i++)
{
for(int j = 0; j < mat.cols; j++)
{
int b = mat.at<cv::Vec3b>(i,j)[0];
int g = mat.at<cv::Vec3b>(i,j)[1];
int r = mat.at<cv::Vec3b>(i,j)[2];
cout << r << " " << g << " " << b << value_rgb <<endl ;
}
}
To read pixel value from a grayscale image
#include <opencv\cv.h>
#include <highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
cv::Mat img = cv::imread("5.jpg",0);
for(int j=0;j<img.rows;j++)
{
for (int i=0;i<img.cols;i++)
{
int a;
a=img.at<uchar>(j,i);
cout<<a<<endl;
}
}
cv::imshow("After",img);
waitKey(0);
}
Updated
This code reads all the grayscale values from an image and results in frequent occurring vales (Number of times the value as occurred). i.e
Number of times pixel value '0' as appeared,
Number of times pixel value '1' as appeared, ... & so on till 256.
#include <opencv\cv.h>
#include <highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
cv::Mat img = cv::imread("5.jpg",0);
//for(int j=0;j<img.rows;j++)
//{
// for (int i=0;i<img.cols;i++)
// {
// int a;
// a=img.at<uchar>(j,i);
// cout<<a<<endl;
// }
//}
vector<int> values_rgb;
for(int i=0; i<20; i++)
{
for(int j=0; j<20; j++)
{
int value_rgb = img.at<uchar>(i,j);
values_rgb.push_back(value_rgb);
//cout << "(" << i << "," << j << ") : " << value_rgb <<endl;
}
}
// Sorting of values in ascending order
vector<int> counter_rg_values;
for(int l=0; l<256; l++)
{
for(int k=0; k<values_rgb.size(); k++)
{
if(values_rgb.at(k) == l)
{
counter_rg_values.push_back(l);
}
}
}
//for(int m=0;m<counter_rg_values.size();m++)
//cout<<m<<" "<< counter_rg_values[m] <<endl;
int m=0;
for(int n=0;n<256;n++)
{
int c=0;
for(int q=0;q<counter_rg_values.size();q++)
{
if(n==counter_rg_values[q])
{
//int c;
c++;
m++;
}
}
cout<<n<<"= "<< c<<endl;
}
cout<<"Total number of elements "<< m<<endl;
cv::imshow("After",img);
waitKey(0);
}
I am trying to train my own detector based on HOG features and i trained a detector with CvSVM utility of opencv. Now to use this detector in HOGDescriptor.SetSVM(myDetector), i need to get trained detector in row-vector (primal) form to feed. For this i am using this code. my implementation is like given below:
vector<float>primal;
void LinearSVM::getSupportVector(std::vector<float>& support_vector) {
CvSVM svm;
svm.load("Classifier.xml");
cin.get();
int sv_count = svm.get_support_vector_count();
const CvSVMDecisionFunc* df = decision_func;
const double* alphas = df[0].alpha;
double rho = df[0].rho;
int var_count = svm.get_var_count();
support_vector.resize(var_count, 0);
for (unsigned int r = 0; r < (unsigned)sv_count; r++) {
float myalpha = alphas[r];
const float* v = svm.get_support_vector(r);
for (int j = 0; j < var_count; j++,v++) {
support_vector[j] += (-myalpha) * (*v);
}
}
support_vector.push_back(rho);
}
int main()
{
LinearSVM s;
s.getSupportVector(primal);
return 0;
}
When i use built-in CvSVM, it shows me SV as 3 bec i have only 3 SV in my saved file but since the decision_func is in protected mode, hence i can not access it. That's why i tried to use that wrapper but still of no use. Perhaps you guys can help me out here... Thanks alot!
Answer with a test harness. I put in new answer as it would add allot of clutter to the original answer, possibly making it a bit confusing.
//dummy features
std:: vector<float>
dummyDerReaderForOneDer(const vector<float> &pattern)
{
int i = std::rand() % pattern.size();
int j = std::rand() % pattern.size();
vector<float> patternPulNoise(pattern);
std::random_shuffle(patternPulNoise.begin()+std::min(i,j),patternPulNoise.begin()+std::max(i,j));
return patternPulNoise;
};
//extend CvSVM to get access to weights
class mySVM : public CvSVM
{
public:
vector<float>
getWeightVector(const int descriptorSize);
};
//get the weights
vector<float>
mySVM::getWeightVector(const int descriptorSize)
{
vector<float> svmWeightsVec(descriptorSize+1);
int numSupportVectors = get_support_vector_count();
//this is protected, but can access due to inheritance rules
const CvSVMDecisionFunc *dec = CvSVM::decision_func;
const float *supportVector;
float* svmWeight = &svmWeightsVec[0];
for (int i = 0; i < numSupportVectors; ++i)
{
float alpha = *(dec[0].alpha + i);
supportVector = get_support_vector(i);
for(int j=0;j<descriptorSize;j++)
{
*(svmWeight + j) += alpha * *(supportVector+j);
}
}
*(svmWeight + descriptorSize) = - dec[0].rho;
return svmWeightsVec;
}
// main harness entry point for detector test
int main (int argc, const char * argv[])
{
//dummy variables for example
int posFiles = 10;
int negFiles = 10;
int dims = 1000;
int randomFactor = 4;
//setup some dummy data
vector<float> dummyPosPattern;
dummyPosPattern.assign(int(dims/randomFactor),1.f);
dummyPosPattern.resize(dims );
random_shuffle(dummyPosPattern.begin(),dummyPosPattern.end());
vector<float> dummyNegPattern;
dummyNegPattern.assign(int(dims/randomFactor),1.f);
dummyNegPattern.resize(dims );
random_shuffle(dummyNegPattern.begin(),dummyNegPattern.end());
// the labels and lables mat
float posLabel = 1.f;
float negLabel = 2.f;
cv::Mat cSvmLabels;
//the data mat
cv::Mat cSvmTrainingData;
//dummy linear svm parmas
SVMParams cSvmParams;
cSvmParams.svm_type = cv::SVM::C_SVC;
cSvmParams.C = 0.0100;
cSvmParams.kernel_type = cv::SVM::LINEAR;
cSvmParams.term_crit = cv::TermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000000, FLT_EPSILON);
cout << "creating training data. please wait" << endl;
int i;
for(i=0;i<posFiles;i++)
{
//your feature for one box from file
vector<float> d = dummyDerReaderForOneDer(dummyPosPattern);
//push back a new mat made from the vectors data, with copy data flag on
//this shows the format of the mat for a single example, (1 (row) X dims(col) ), as training mat has each **row** as an example;
//the push_back works like vector add adds each example to the bottom of the matrix
cSvmTrainingData.push_back(cv::Mat(1,dims,CV_32FC1,d.data(),true));
//push back a pos label to the labels mat
cSvmLabels.push_back(posLabel);
}
//do same with neg files;
for(i=0;i<negFiles;i++)
{
float a = rand();
vector<float> d = dummyDerReaderForOneDer(dummyNegPattern);
cSvmTrainingData.push_back(cv::Mat(1,dims,CV_32FC1,d.data(),true));
cSvmLabels.push_back(negLabel);
}
//have a look
cv::Mat viz;
cSvmTrainingData.convertTo(viz,CV_8UC3);
viz = viz*255;
cv::imshow("svmData", viz);
cv::waitKey(10);
cout << "press any key to continue" << endl;
getchar();
viz.release();
//create the svm;
cout << "training, please wait" << endl;
mySVM svm;
svm.train(cSvmTrainingData,cSvmLabels,cv::Mat(),cv::Mat(),cSvmParams);
cout << "get weights" << endl;
vector<float> svmWeights = svm.getWeightVector(dims);
for(i=0; i<dims+1; i++)
{
cout << svmWeights[i] << ", ";
if(i==dims)
{
cout << endl << "bias: " << svmWeights[i] << endl;
}
}
cout << "press any key to continue" << endl;
getchar();
cout << "testing, please wait" << endl;
//test the svm with a large amount of new unseen fake one at a time
int totExamples = 10;
int k;
for(i=0;i<totExamples; i++)
{
cout << endl << endl;
vector<float> dPos = dummyDerReaderForOneDer(dummyPosPattern);
cv::Mat dMatPos(1,dims,CV_32FC1,dPos.data(),true);
float predScoreFromDual = svm.predict(dMatPos,true);
float predScoreBFromPrimal = svmWeights[dims];
for( k = 0; k <= dims - 4; k += 4 )
predScoreBFromPrimal += dPos[k]*svmWeights[k] + dPos[k+1]*svmWeights[k+1] +
dPos[k+2]*svmWeights[k+2] + dPos[k+3]*svmWeights[k+3];
for( ; k < dims; k++ )
predScoreBFromPrimal += dPos[k]*svmWeights[k];
cout << "Dual Score:\t" << predScoreFromDual << "\tPrimal Score:\t" << predScoreBFromPrimal << endl;
}
cout << "press any key to continue" << endl;
getchar();
return(0);
}
Hello again :) please extend the cvsm class rather than encapsulating it, as you need access to protected member.
//header
class mySVM : public CvSVM
{
public:
vector<float>
getWeightVector(const int descriptorSize);
};
//cpp
vector<float>
mySVM::getWeightVector(const int descriptorSize)
{
vector<float> svmWeightsVec(descriptorSize+1);
int numSupportVectors = get_support_vector_count();
//this is protected, but can access due to inheritance rules
const CvSVMDecisionFunc *dec = CvSVM::decision_func;
const float *supportVector;
float* svmWeight = &svmWeightsVec[0];
for (int i = 0; i < numSupportVectors; ++i)
{
float alpha = *(dec[0].alpha + i);
supportVector = get_support_vector(i);
for(int j=0;j<descriptorSize;j++)
{
*(svmWeight + j) += alpha * *(supportVector+j);
}
}
*(svmWeight + descriptorSize) = - dec[0].rho;
return svmWeightsVec;
}
something like that.
credits:
Obtaining weights in CvSVM, the SVM implementation of OpenCV