openCV creating a 3D matrix with different sizes - c++

accroding to this
http://answers.opencv.org/question/15917/how-to-access-data-from-a-cvmat/
I have tried to create a 3D matrix
void AutomaticMacbethDetection::DrawMacbethROI(ColorCheckerBatchRGB ColorCheckerBatchRGB, int *** raw_frame,int _width, int _height,int colorOrder)
{
cv::Mat src;
if (colorOrder == -1)
{
const int sizes[3]={_height,_width,3};
src = cv::Mat::zeros(3, sizes, CV_32F);
}else
{
const int sizes[3]={_height,_width,1};
src = cv::Mat::zeros(3, sizes, CV_32F);
}
std::vector<float> channel;
if (colorOrder == -1)
{
for (int w = 0; w < _width; w++)
{
for (int h = 0; h < _height; h++)
{
float temp =raw_frame[h][w][0];
channel.push_back(temp);
src.at<float>(h,w,0) = temp;
src.at<float>(h,w,1) = raw_frame[h][w][1];
src.at<float>(h,w,2) = raw_frame[h][w][2];
}
}
}
else
{
for (int w = 0; w < _width; w++)
{
for (int h = 0; h < _height; h++)
{
float temp =raw_frame[h][w][0];
channel.push_back(temp);
src.at<float>(h,w,0) = temp;
}
}
float divider = Utilities::tprctile(channel,99.2);
src = src/divider;
}
cv::imshow("test", src);
cv::waitKey(0);
}
my function supports both RGB and Raw Image so I need to create a 100x100x1 matrix or a 100x100x3 matrix, depending on the image type.
however I get an exception in imshow()
OpenCV Error: Assertion failed (p[-1] <= 2) in cv::Mat::MSize::operator (), file
C:\buildslave64\win64_amdocl\2_4_PackSlave-win64-vc11-shared\opencv\modules\cor
e\include\opencv2/core/mat.hpp, line 712
can you please explain what is the problem?

It looks to me that you are trying to set a 3-layer zero mat in both cases:
const int sizes[3]={_height,_width,1};
src = cv::Mat::zeros(3, sizes, CV_32F);
C++: static MatExpr Mat::zeros(int ndims, const int* sz, int type) states that the first argument is the dimentions. This should here be 1 if you want a 1-layer mat.

The solution I have found for this is using CV_32FC3 which means each cell of the matrix (x,y) has 3 values in it.
this is how you init the 3D matrix.
src = cv::Mat::zeros(_height,_width, CV_32FC3);
and now you have 3 cells which you need to access like so:
src.at<cv::Vec3f>(h,w)[0]
src.at<cv::Vec3f>(h,w)[1]
src.at<cv::Vec3f>(h,w)[2]
Please notice I'm using Vec3f and not float like i'm using in CV_32F
void AutomaticMacbethDetection::DrawMacbethROI(ColorCheckerBatchRGB ColorCheckerBatchRGB, int *** raw_frame,int _width, int _height,int colorOrder)
{
cv::Mat src;
std::vector<float> channel;
if (colorOrder != -1 )
{
src = cv::Mat::zeros(_height,_width, CV_32F);
for (int w = 0; w < _width; w++)
{
for (int h = 0; h < _height; h++)
{
float temp =raw_frame[h][w][0];
channel.push_back(temp);
src.at<float>(h,w) = temp;
}
}
float divider = Utilities::tprctile(channel,99.2);
src = src/divider;
}
else
{
src = cv::Mat::zeros(_height,_width, CV_32FC3);
for (int w = 0; w < _width; w++)
{
for (int h = 0; h < _height; h++)
{
float temp =raw_frame[h][w][0];
channel.push_back(temp);
src.at<cv::Vec3f>(h,w)[0] = raw_frame[h][w][0];
src.at<cv::Vec3f>(h,w)[1] = raw_frame[h][w][1];
src.at<cv::Vec3f>(h,w)[2] = raw_frame[h][w][2];
}
}
float divider = Utilities::tprctile(channel,99.2);
src = src/divider;
}
cv::resize(src,src,cv::Size(),0.3,0.3,cv::INTER_LINEAR);
cv::imshow("detected", src);
cv::waitKey(0);

Related

OpenCV Using a loop to sum a part of your image error?

I am wanting to move through an image and take a 5x5 grid centered around each pixel in the image. I then want to sum that grid and compare it to a threshold.
int main()
{
Mat element = getStructuringElement(MORPH_RECT, Size(7, 7));
Mat im = imread("blob.png", IMREAD_GRAYSCALE);
bool fromCenter = false;
namedWindow("Crop frame", WINDOW_NORMAL);
Rect2d r = selectROI("Crop frame", im, fromCenter);
im = im(r);
erode(im, im, element);
Mat clone = im;
int sectionSize = 4;
int width = im.cols - sectionSize/2;
int height = im.rows - sectionSize/2;
int sum = 0;
int counter = 0;
for (int i = sectionSize/2; i < width; i++) {
for (int j = sectionSize/2; j < height; j++) {
Rect rect = Rect(i, j, sectionSize, sectionSize);
rect -= Point(rect.width / 2, rect.height / 2);
Mat temp = im(rect);
for (int x = 0; x < temp.cols; x++) {
for (int y = 0; y < temp.rows; y++) {
int pixelValue = (int)temp.at<uchar>(y, x);
sum += pixelValue;
}
}
cout << sum << endl;
if (sum > 3800) {
clone.at<uchar>(j, i) = 255;
}
else {
clone.at<uchar>(j, i) = 0;
}
namedWindow("erode", WINDOW_NORMAL);
imshow("erode", clone);
waitKey(1);
sum = 0;
}
}
}
I am getting fluctuations in the pixel sum based on where I select my ROI in the image even when both over white space Also, my pixel sum is changing when I change the value of the clone pixel in this section of the code which I do not understand at all:
if (sum > 3800) {
clone.at<uchar>(j, i) = 255;
}
else {
clone.at<uchar>(j, i) = 0;
}

cannot Segment a RGB image by pointer based accessing pixel intensities

I define a function void segRgb(Mat &src, Mat &dst, Rect roi), using which I try to segment the region of region (ROI) of an input RGB image by simply thresholding a lumped pixel intensities derived from R, G and B channels. Here below is the code of the function:
void segRgb(Mat &src, Mat &dst, Rect roi)
{
uchar *bgrdata = src.data;
uchar *outdata = dst.data;
int ystart = roi.y;
int yend = roi.y + roi.height;
int xstart = roi.x;
int xend = roi.x+roi.width;
int step1 = src.cols-roi.width;
int step3 = 3*step1;
int start1 = roi.y*src.cols+roi.x;
int start3 = 3*start1;
bgrdata += start3;
outdata += start1;
uchar r, g, b;
double score=0.0;
for(int i=ystart; i<yend; i++)
{
qDebug()<<"Rows: "<<i;
for(int j=xstart; j<xend; j++)
{
b = *bgrdata++;
g = *bgrdata++;
r = *bgrdata++;
score = 0.21*r+0.72*g+0.07*b; //a simple rule to lump RGB values
if(score>100)
{
*outdata = 255;
}
else
{
*outdata = 0;
}
outdata++;
}
outdata+=step1;
bgrdata+=step3;
}
}
Following is my test code for the function:
Rect cvRect = Rect(10,50,256,256);
Mat dst;
segRgb(im, dst, cvRect); //im is a loaded Matrix of 427*640*3, CV_8UC3
namedWindow("Thresholded");
imshow("Thresholed", dst);
I run the codes above. The function segRgb does not work for some reason. No image is shown. Actually, the loop inside the segRgb does not proceed. Anyone can point to the problem, debug my codes bit? Thanks!
void segRgb(Mat &src, Mat &dst, Rect roi)
{
uchar *bgrdata = src.data;
uchar *outdata = dst.data;
int ystart = roi.y;
int yend = roi.y + roi.height;
int xstart = roi.x;
int xend = roi.x + roi.width;
int step1 = src.cols - roi.width;
int step3 = 3 * step1;
int start1 = roi.y*src.cols + roi.x;
int start3 = 3 * start1;
bgrdata += start3;
outdata += start1;
uchar r, g, b;
double score = 0.0;
for (int i = ystart; i < yend; i++)
{
cout << "Rows: " << i;
for (int j = xstart; j < xend; j++)
{
b = *bgrdata++;
g = *bgrdata++;
r = *bgrdata++;
score = 0.21*r + 0.72*g + 0.07*b; //a simple rule to lump RGB values
if (score > 100)
{
*outdata = 255;
}
else
{
*outdata = 0;
}
outdata++;
}
outdata += step1;
bgrdata += step3;
}
}
int main() {
Mat im = imread("urimage");
Rect cvRect = Rect(10, 50, 256, 256);
// you have to allocate a size for the dst Mat otherwise the uchar* output you point to above will be garbage
Mat dst(im.size(),im.type());
segRgb(im, dst, cvRect); //im is a loaded Matrix of 427*640*3, CV_8UC3
//Resize you dst or you can change a bit in your function paramters to get it directly
dst=Mat(dst, cvRect);
namedWindow("Thresholded");
imshow("Thresholed", dst);
waitKey(0);
}

Histogram Equalization implementation using openCV C++

I am doing my own implementation of histogram equalization, but it produces some creepy looking images.
I got the color intensity of every pixel, then I got the probability by dividing the color intensity by the number of pixels in the picture. Then, I made a cumulative probability array that I later multiplied by 255 and floored it. This value ended up being the new color. What am I missing?
Before equalization
After equalization
My code:
void pixelFrequency(Mat img, int intensity[])
{
for (int j = 0; j < img.rows; j++)
for (int i = 0; i < img.cols; i++)
intensity[int(img.at<uchar>(j, i))]++;
}
void pixelProbability(Mat img, double probability[], int intensity[])
{
for (int i = 0; i < 256; i++)
probability[i] = intensity[i] / double(img.rows * img.cols);
}
void cumuProbability(double probability[], double cumulativeProbability[])
{
cumulativeProbability[0] = probability[0];
for (int i = 1; i < 256; i++)
cumulativeProbability[i] = probability[i] + cumulativeProbability[i - 1];
}
void histogramEqualization(Mat& img, int intensity[], double probability[], double cumulativeProbability[])
{
pixelFrequency(img, intensity);
pixelProbability(img, probability, intensity);
cumuProbability(probability, cumulativeProbability);
for (int i = 0; i < 256; i++)
cumulativeProbability[i] = floor(cumulativeProbability[i] * 255);
for (int j = 0; j < img.rows; j++)
{
for (int i = 0; i < img.cols; i++)
{
//int color = cumulativeProbability[int(img.at<uchar>(i, j))];
img.at<uchar>(j, i) = cumulativeProbability[int(img.at<uchar>(i, j))];
}
}
}
int main()
{
int intensity[256] = { 0 };
double probability[256] = { 0 };
double cumulativeProbability[256] = { 0 };
Mat img = imread("ex.jpg", CV_LOAD_IMAGE_GRAYSCALE);
histogramEqualization(img, intensity, probability, cumulativeProbability);
namedWindow("image", WINDOW_AUTOSIZE);
imshow("image", img);
waitKey(0);
return 0;
}

Converting Caffe caffe::Datum to OpenCV cv::Mat in C++

I'm doing some debugging and so I'm dumping image files to look at the predictions and transformations.
I can create a caffe::Datum from cv::Mat:
cv::Mat matrix;
// ... initialize matrix
caffe::Datum datum;
caffe::CVMatToDatum(matrix, &datum)
but how do I create a cv::Mat from caffe::Datum? The following code gives the fatal exception "Datum not encoded":
caffe::Datum datum;
// ... initialize datum
cv::Mat matrix;
matrix = DecodeDatumToCVMat(datum, true);
You can use following functions.
cv::Mat DatumToCVMat(const Datum& datum){
int datum_channels = datum.channels();
int datum_height = datum.height();
int datum_width = datum.width();
string strData = datum.data();
cv::Mat cv_img;
if (strData.size() != 0)
{
cv_img.create(datum_height, datum_width, CV_8UC(datum_channels));
const string& data = datum.data();
std::vector<char> vec_data(data.c_str(), data.c_str() + data.size());
for (int h = 0; h < datum_height; ++h) {
uchar* ptr = cv_img.ptr<uchar>(h);
int img_index = 0;
for (int w = 0; w < datum_width; ++w) {
for (int c = 0; c < datum_channels; ++c) {
int datum_index = (c * datum_height + h) * datum_width + w;
ptr[img_index++] = static_cast<uchar>(vec_data[datum_index]);
}
}
}
}
else
{
cv_img.create(datum_height, datum_width, CV_32FC(datum_channels));
for (int h = 0; h < datum_height; ++h) {
float* ptr = cv_img.ptr<float>(h);
int img_index = 0;
for (int w = 0; w < datum_width; ++w) {
for (int c = 0; c < datum_channels; ++c) {
ptr[img_index++] = static_cast<float>(datum.float_data(img_index));
}
}
}
}
return cv_img;
}
all code :
http://lab.deepaivision.com/2017/06/opencv-mat-caffe-datum-datum-mat.html
Addition to the answer by #ttagu99 , in the float section there is a slight bug:
The line:
ptr[img_index++] = static_cast<float>(datum.float_data(img_index));
Should be in fact:
int datum_index = (c * datum_height + h) * datum_width + w;
ptr[img_index++] = static_cast<float>(datum->float_data(datum_index));
This fixes the order of writing the data to the matrix. Otherwise, you only see lines of color.

load cv::mat to faster rcnn blob

Currently I am working with Faster RCNN using C++. I am trying to load cv Mat object (color image) to the net_->blob_by_name("data"). I follow the given instruction here https://github.com/YihangLou/FasterRCNN-Encapsulation-Cplusplus but the result is really bad:
I didn't change anything from the original code. So I suspect loading data to blob might be the issue.
Code:
float im_info[3];
float data_buf[height*width*3];
float *boxes = NULL;
float *pred = NULL;
float *pred_per_class = NULL;
float *sorted_pred_cls = NULL;
int *keep = NULL;
const float* bbox_delt;
const float* rois;
const float* pred_cls;
int num;
for (int h = 0; h < cv_img.rows; ++h )
{
for (int w = 0; w < cv_img.cols; ++w)
{
cv_new.at<cv::Vec3f>(cv::Point(w, h))[0] = float(cv_img.at<cv::Vec3b>(cv::Point(w, h))[0])-float(102.9801);
cv_new.at<cv::Vec3f>(cv::Point(w, h))[1] = float(cv_img.at<cv::Vec3b>(cv::Point(w, h))[1])-float(115.9465);
cv_new.at<cv::Vec3f>(cv::Point(w, h))[2] = float(cv_img.at<cv::Vec3b>(cv::Point(w, h))[2])-float(122.7717);
}
}
cv::resize(cv_new, cv_resized, cv::Size(width, height));
im_info[0] = cv_resized.rows;
im_info[1] = cv_resized.cols;
im_info[2] = img_scale;
for (int h = 0; h < height; ++h )
{
for (int w = 0; w < width; ++w)
{
data_buf[(0*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[0]);
data_buf[(1*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[1]);
data_buf[(2*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[2]);
}
}
net_->blob_by_name("data")->Reshape(1, 3, height, width);
net_->blob_by_name("data")->set_cpu_data(data_buf);
net_->blob_by_name("im_info")->set_cpu_data(im_info);
net_->ForwardFrom(0);
bbox_delt = net_->blob_by_name("bbox_pred")->cpu_data();
num = net_->blob_by_name("rois")->num();
Any advices ?
Can you please modify the code and check ...
cv::resize(cv_new, cv_resized, cv::Size(width, height));
im_info[0] = cv_resized.rows;
im_info[1] = cv_resized.cols;
im_info[2] = img_scale;
net_->blob_by_name("data")->Reshape(1, 3, height, width);
const shared_ptr<Blob<float> >& data_blob = net_->blob_by_name("data");
float* data_buf = data_blob->mutable_cpu_data();
for (int h = 0; h < height; ++h )
{
for (int w = 0; w < width; ++w)
{
data_buf[(0*height+h)*width+w] = float(cv_resized.at<cv::Vec3f> cv::Point(w, h))[0]);
data_buf[(1*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[1]);
data_buf[(2*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[2]);
}
}
net_->Forward();