OrbFeaturesFinder giving different result when implemented on Android platform - opencv

I am using OrbFeaturesFinder to detect keypoints in Images.
Ptr<FeaturesFinder> finder;
finder = makePtr<OrbFeaturesFinder>();
vector<ImageFeatures> features(num_images);
(*finder)(img, features[i]);
I used this code on linux and implemented the same on android, but the results are different sometimes, as in given link
http://imgur.com/a/wQXZx
What can be reason behind this nature of output.
method of accessing images in android
Image is saved in jpeg form, then read[edit] -
for(int i = 0; i < imgNames.size(); i++){
Bitmap bitmap = getThumbnail(imgNames.get(i));
int imageW = bitmap.getWidth();
int imageH = bitmap.getHeight();
byte[] rgb = getByteArray(imageW, imageH, bitmap, "RGB");
bitmap.recycle();
Mat mRgb = new Mat(imageH, imageW, CvType.CV_8UC3);
mRgb.put(0, 0, rgb);
Imgproc.cvtColor(mRgb, mRgb, Imgproc.COLOR_BGR2RGB, 3);
panoImgs.add(mRgb);
}
and sent to jni -
jclass matClass = env->FindClass("org/opencv/core/Mat");
jmethodID getNativeAddr = env->GetMethodID(matClass, "getNativeObjAddr", "()J");
int numImgs = env->GetArrayLength(jInputArray);
vector<Mat> natImgs;
for(int i=0; i < numImgs; ++i) {
natImgs.push_back(
*(Mat*)env->CallLongMethod(
env->GetObjectArrayElement(jInputArray, i),
getNativeAddr
)
);
}
for linux - I am saving the same image in jpeg format and then using imread to access files.

Related

Load UIImage to float array for DeepLearningKit usage

I'd like to use the DeepLearningKit for iOS. I want to use UIImage objects to be classified. The sample application only uses a float array loaded from a json file. Thus I have to create the bitmap representation of the UIImage as a float array and use this for the classify-method.
Can anybody help me on that? Is there a way to create a bitmap representation for UIImage? Moreover I have to swap the channels from RGB to BGR.
Thank you
Have added an extension to UIImage that allows setting and getting RGB(A) pixels directly - key methods:
public func setPixelColorAtPoint(point:CGPoint, color: RawColorType) -> UIImage?
func getPixelColorAtLocation(point:CGPoint)->UIColor?
where RawColorType is defined as
public typealias RawColorType = (newRedColor:UInt8, newgreenColor:UInt8, newblueColor:UInt8, newalphaValue:UInt8)
This way you should be able to convert back and forth between bitmap representation and UIImage. Wrote a blog post that gives some more context: http://deeplearningkit.org/tutorials-for-ios-os-x-and-tvos/tutorial-image-handling-in-deeplearningkit/
I've write a function to convert a image file to Caffe blob on iOS platform. You can find it here. I hope it will help you.
Code snippet:
// Convert Bitmap (channels*width*height) to Matrix (width*height*channels)
// Remove alpha channel
int input_channels = input_layer->channels();
LOG(INFO) << "image_channels:" << image_channels << " input_channels:" << input_channels;
if (input_channels == 3 && image_channels != 4) {
LOG(ERROR) << "image_channels input_channels not match.";
return false;
} else if (input_channels == 1 && image_channels != 1) {
LOG(ERROR) << "image_channels input_channels not match.";
return false;
}
float *input_data = input_layer->mutable_cpu_data();
for (size_t h = 0; h < height; h++) {
for (size_t w = 0; w < width; w++) {
for (size_t c = 0; c < input_channels; c++) {
// OpenCV use BGR instead of RGB
size_t cc = c;
if (input_channels == 3) {
cc = 2 - c;
}
// Convert uint8_t to float
input_data[c*width*height + h*width + w] =
static_cast<float>(result[h*width*image_channels + w*image_channels + cc]);
if (mean.size() == input_channels) {
input_data[c*width*height + h*width + w] -= mean[c];
}
}
}
}

Understanding StereoMatching in Point Cloud Library

Situation: I am trying to get point cloud with pcl::AdaptiveCostSOStereoMatching, which uses two rectified images (pics are ok).
I used these tutorials to learn how to do this:
First tutorial
Second tutorial
Error: programm crashes in runtime when calling "compute" method of AdaptiveCostSOStereoMatching
Question: how to correctly pass images to "compute" method?
I tried:
1) Images converted by png2pcd
(command line: "png2pcd.exe in.png out.pcd")
2) Images converted with function below from cv::Mat
But no luck.
Function which converts cv::Mat to pcl::PointCloud
void MatToPointCloud(Mat& mat, pcl::PointCloud<RGB>::Ptr cloud)
{
int width = mat.cols;
int height = mat.rows;
pcl::RGB val;
val.r = 0; val.g = 0; val.b = 0;
for (int i = 0; i < mat.rows; i++)
for (int j = 0; j < mat.cols; j++)
{
auto point = mat.at<Vec3b>(i, j);
//std::cout << j << " " << i << "\n";
val.b = point[0];
val.g = point[1];
val.r = point[2];
cloud->at(j, i) = val;
}
}
pcl::AdaptiveCostSOStereoMatching (compute)
// Input
Mat leftMat, rightMat;
leftMat = imread("left.png");
rightMat = imread("right.png");
int width = leftMat.cols;
int height = rightMat.rows;
pcl::RGB val;
val.r = 0; val.g = 0; val.b = 0;
pcl::PointCloud<pcl::RGB>::Ptr left_cloud(new pcl::PointCloud<pcl::RGB>(width, height, val));
pcl::PointCloud<pcl::RGB>::Ptr right_cloud(new pcl::PointCloud<pcl::RGB>(width, height, val));
MatToPointCloud(leftMat, left_cloud);
MatToPointCloud(rightMat, right_cloud);
// Calculation
pcl::AdaptiveCostSOStereoMatching stereo;
stereo.setMaxDisparity(60);
//stereo.setXOffest(0); Почему-то не распознается
stereo.setRadius(5);
stereo.setSmoothWeak(20);
stereo.setSmoothStrong(100);
stereo.setGammaC(25);
stereo.setGammaS(10);
stereo.setRatioFilter(20);
stereo.setPeakFilter(0);
stereo.setLeftRightCheck(true);
stereo.setLeftRightCheckThreshold(1);
stereo.setPreProcessing(true);
stereo.compute(*left_cloud, *right_cloud); // <-- CRASHING THERE
stereo.medianFilter(4);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr out_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
stereo.getPointCloud(318.11220, 224.334900, 368.534700, 0.8387445, out_cloud, left_cloud);
Error information:
Output log: HEAP[App.exe]:
Heap block at 0000006B0F828460 modified at 0000006B0F8284A8 past requested size of 38
App.exe has triggered a breakpoint.
left_cloud (a right cloud looks like left_cloud)
Mini question: if AdaptiveCostSOStereoMatching really allows build point cloud from 2 images, how ACSSM doing this without insintric and excentic parameters?
Problem: I downloaded and installed old version of PCL without stereo.
After that, I downloaded stereo from other PCL pack and add this library to my PCL pack. And it worked incorrectly.
Solution: I compilled PCL 1.8 and my programm is ok now.
OS: Windows
IDE: MSVS 12 2013 x64
If you will try to compile PCL, these links can help you:
Official-tutorial-1
Official-tutorial-2
Good help with FLANN and VTK
Example to verify installation

How do I get the RGB values of an Image?

I am taking a computer graphics class, and I need to work with textures, but I can't use any library to do it. I am stuck on loading the rgb values of the images I need to use (the images can be in any format, jpg, raw, png, etc..) so my question is, which is the easiest way to get the rgb values of an image (of any format) without using any libraries to get this values?? Here is what I found already on the site:
unsigned char *data;
File *file;
file = fopen("image.png", "r");//
data = (unsigned char *)malloc(TH*TV*3); //TH and TV are both 50
fread(data, TH*TV*3, 1, file);
fclose(file);
int i;
for(i=0;i<TH*TV*3;i++){
//suposing I have a struct RGB for the rgb values
RGB.r = data[?];// how do I get the r value
RGB.g = data[?];// how do I get the g value
RGB.b = data[?];// how do I get the b value
}
Thanks
Rather than iterating through every byte that you read in, you want to iterate every pixel which consists of 3 bytes. So replace i++ with i+=3.
for(i=0;i<TH*TV*3;i+=3){
RGB.r = data[i];
RGB.g = data[i+1];
RGB.b = data[i+2];
}
Try to use some framework like OpenCV there are several options to get the colors or to manipulate an image.
Here I found this example code:
cv::Mat img = cv::imread("lenna.png");
for(int i=0; i<img.rows; i++) {
for(int j=0; j<img.cols; j++) {
// You can now access the pixel value with cv::Vec3b
std::cout << img.at<cv::Vec3b>(i,j)[0] << " ";
str::cout << img.at<cv::Vec3b>(i,j)[1] << " ";
str::cout << img.at<cv::Vec3b>(i,j)[2] << std::endl;
}
}
But please note that the code above is not very performance, but the code above should give you an idea how to read the pixels.

Compile error in CV_MAT_ELEM

As a result of a call to estimateRigidTransform() I get a cv::Mat object named "trans". To retrieve its contained matrix I try to access its elements this way:
for (i=0; i<2; i++) for (j=0; j<3; j++)
{
mtx[j][i]=CV_MAT_ELEM(trans,double,i,j);
}
Unfortunately with VS2010 I get a compiler error
error C2228: left of '.ptr' must have class/struct/union
for the line with CV_MAT_ELEM. When I unwrap this macro I find something like
(mat).data.ptr + (size_t)(mat).step*(row) + (pix_size)*(col))
When I remove the ".ptr" behind (mat).data it compiles. But I can't imagine that's the solution (or can't imagine that's a bug and I'm the only one who noticed it). So what could be wrong here really?
Thanks!
You don't access the mat elements like this. For a traversal see my other answer here with sample code:
color matrix traversal
or see the opencv refman for grayscale Mat:
Mat M; // should be grayscale
int cols = M.cols, rows = M.rows;
for(int i = 0; i < rows; i++)
{
const double* Mi = M.ptr<double>(i);
for(int j = 0; j < cols; j++)
{
Mi[j]; // is the matrix element.
}
}
Just an addendum from my side: meanwhile I found CV_MAT_ELEM expects a structure CvMat (OpenCV-C-interface) but not cv::Mat (the C++-interface). That's why I get this funny error. Conversion from cv::Mat to CvMat can be done simply by casting to CvMat. Funny confusion with the C and C++ interfaces in OpenCV...

Bug in OpenCV2.3 cv::split() function. Identical values in all 3 channels

After spending a couple of days trying figure out why opencv DFT would give 100% similar results for all three channels I ended up finding out that there might be a bug in the split() function that OpenCV provides for splitting a input image to 3 single channel images.
std::vector<cv::Mat> rgbChannels(3,cv::Mat(inputImage.size(),CV_64FC1));
cv::split(inputImage, rgbChannels);
After saving the image values onto disk and using a file differencing tool, I found out that all values in the split channels were identical.
Have I done something wrong?
My work around was the following function. But that also gave me the exact identical values, giving me a hint that somehow vectors were not being handled correctly by OpenCV.
SplitImage(cv::Mat inputImage)
{
//copy original in BGR order
std::vector<cv::Mat> splittedImage(3,cv::Mat(inputImage.size(),CV_64FC1));
cv::Mat tempImage(inputImage.size(),CV_64FC1);
for (int row = 0; row < inputImage.size().height; row++)
{
for (int col = 0; col < inputImage.size().width; col++)
{
splittedImage[0].at<double>(row, col) = inputImage.at<cv::Vec3d>(row, col)[0];
splittedImage[1].at<double>(row, col) = inputImage.at<cv::Vec3d>(row, col)[1];
splittedImage[2].at<double>(row, col) = inputImage.at<cv::Vec3d>(row, col)[2];
}
}
return splittedImage;
}
And finally wrote the following to solve the problem
SplitImage(cv::Mat inputImage)
{
//copy original in BGR order
std::vector<cv::Mat> splittedImage(3,cv::Mat(inputImage.size(),CV_64FC1));
std::vector<cv::Mat>::iterator it;
it = splittedImage.begin();
for(int channelNo = 0; channelNo < inputImage.channels(); channelNo++)
{
cv::Mat tempImage(inputImage.size(),CV_64FC1);
for (int row = 0; row < inputImage.size().height; row++)
{
for (int col = 0; col < inputImage.size().width; col++)
{
tempImage.at<double>(row, col) = inputImage.at<cv::Vec3d>(row, col)[channelNo];
}
}
it = splittedImage.insert ( it , tempImage );
it++;
}
return splittedImage;
}
Has anyone had a problem with split() function or have I done something wrong?
It is not a bug in OpenCV but there is a problem with your code.
The following line does not create a vector of 3 different Mats:
std::vector<cv::Mat> rgbChannels(3,cv::Mat(inputImage.size(),CV_64FC1));
Instead, this line produces a vector of 3 Mat headers sharing the same memory. It works this way because Mat copy constructor does not make a deep copy - it just increments an internal reference counter.
Just change your code to the following to solve your problem:
std::vector<cv::Mat> rgbChannels(3);
cv::split(inputImage, rgbChannels);

Resources