Is there a built-in way to downsample an image in OpenCV 2.3.1 without prior Gaussian smoothing (which is performed by pyrDown C++ function).
Thanks.
Maybe you're looking for resize().
# Python code:
import cv2
large_img = cv2.imread('our_large_image.jpg')
small_to_large_image_size_ratio = 0.2
small_img = cv2.resize(large_img, # original image
(0,0), # set fx and fy, not the final size
fx=small_to_large_image_size_ratio,
fy=small_to_large_image_size_ratio,
interpolation=cv2.INTER_NEAREST)
Instead of interpolation=cv2.INTER_NEAREST you can use any of these interpolation methods.
resize() with interpolation= INTER_NEAREST.
EDIT
hmmm, what if you write the function yourself?
double factor;
int newcols = round(mat.cols*factor);
int newrows = round(mat.rows*factor);
Mat newmat = Mat(newcol, newrows, mat.type());
for (int i=0;i<mat.cols;i++){
for (int j=0;j<mat.cols;j++){
newmat_<yourtype> (round(i*factor), round(j*factor)) = mat_<yourtype>(i, j);
}
}
I haven't checked whether the code works or not (most likely not), but you get the idea.
You can use Image Pyramids: pyrDown, the links of the opencv document is
http://docs.opencv.org/2.4/doc/tutorials/imgproc/pyramids/pyramids.html
Related
I need to write an own implementation of computing the fundamental matrix between two images based on the corresponding image coordinates without using OpenCV.
Is it possible to describe this algorithm in its simplest form in accordance with the following function? a simple and straightforward formula.
FMatrixEightPoint()
Input Arguments:
points1(x,y)−pixel coordinates in the first image ,
corresponding to points2 in the second image
points2(x,y)−pixel coordinates in the second image ,
corresponding to points1 in the first image
Output :
F − the fundamental matrix between the first image and the second image
Yes, it is possible to describe the algorithm in the mentioned form.
If you would use OpenCV, you could just use findFundamentalMat. This also provides the 8-point method for computing the fundamental matrix.
The example (in C++) taken from the OpenCV documentation, but adapted (using the RANSAC algorithm for computing the fundamental matrix):
// Example. Estimation of fundamental matrix using the 8-point algorithm
int point_count = 8; // must be >= 8
vector<Point2f> points1(point_count);
vector<Point2f> points2(point_count);
// initialize the points here ... */
for( int i = 0; i < point_count; i++ )
{
points1[i] = ...;
points2[i] = ...;
}
Mat fundamental_matrix =
findFundamentalMat(points1, points2, CV_FM_8POINT);
If you want to write your own function, it would look like this (no valid code)
Matrix findFundamentalMat(Array points1, Array points2)
{
Matrix fundamentalMatrix;
// compute fundamental matrix based on input points1 and points2 or call OpenCV's findFundamentalMat
return fundamentalMatrix;
}
I am someone who is new to openCV and has been trying to use convexhull function in the openCV library for an app (objective-C being used), I need to know what is the input format of function arguments, it's pretty confusing. And does this function return the points in a sequence? Like, if I use addLineToPoint to draw a bezierpath of this hull, is it possible?
Some sample code for you:
std::vector<cv::Point> points;
//fill that vector with your points
std::vector<cv::Point> hull;
if (points.size()) {
cv::convexHull(points, hull);
}
cv::Size size = cv::Size(w, h);
//some size for the matrix where you will draw your convex hull
cv::Mat hullMask = Mat::zeros(size, CV_8UC1);
int hull_count = (int)hull.size();
if (hull_count) {
const cv::Point* hull_pts = &hull[0];
cv::fillPoly(hullMask, &hull_pts, &hull_count, 1, cv::Scalar(255));
}
This code will help you to create convex hull and draw it.
Here you can find complete documentation for that function. It will return points in a sequence according to the "clockwise" argument. By default it will be counter-clockwise.
I try to blend my images into pano with MultiBandBlender, but it return black pano. But FeatherBlender works fine. What I doing wrong?
blendImages(const std::vector<cv::Point> &corners, std::vector<cv::Mat> images)
{
std::vector<cv::Size> sizes;
for(int i = 0; i < images.size(); i++)
sizes.push_back(images[i].size());
float blend_strength = 5;
cv::Size dst_sz = cv::detail::resultRoi(corners, sizes).size();
float blend_width = sqrt(static_cast<float>(dst_sz.area())) * blend_strength / 100.f;
cv::Ptr<cv::detail::Blender> blender = cv::detail::Blender::createDefault(cv::detail::Blender::MULTI_BAND);
//cv::detail::FeatherBlender* fb = dynamic_cast<cv::detail::FeatherBlender*>(blender.get());
//fb->setSharpness(1.f/blend_width);
cv::detail::MultiBandBlender* mb = dynamic_cast<cv::detail::MultiBandBlender*>(blender.get());
mb->setNumBands(static_cast<int>(ceil(log(blend_width)/log(2.)) - 1.));
blender->prepare(corners, sizes);
for(int i = 0; i < images.size(); i++)
{
cv::Mat image_s;
images[i].convertTo(image_s, CV_16SC3);
blender->feed(image_s, cv::Mat::ones(image_s.size(), CV_8UC1), corners[i]);
}
cv::Mat pano;
cv::Mat panoMask = cv::Mat::ones(dst_sz, CV_8UC1);
blender->blend(pano, panoMask);
return pano;
}
Three possible causes:
Try keeping all image_s and masks in a vector, and feed with the following structure:
for (int i = 0; i < images_s.size(); ++i)
blender->feed(images_s[i], masks[i], corners[i]);
Don't initialize panoMask to ones before blending.
Make sure corners are well defined
Actually, I can't compile your code with OpenCV 2.4, because of blender.get function. There is no such a function in my build of OpenCV 2.4.
Anyway, if you wish to make a panorama, you'd better not use resultRoi function. You need boundingRect. I suppose, it is really hard to get all horizontally aligned images for one panorama.
Also, look at my answer here. It demonstrates how to use MultiBandBlender.
Hey I was getting the same black pano while using MultiBand blender in opencv. Actually the issue was resolved by changing
cv::Mat::ones(image_s.size(), CV_8UC1)
to
cv::Mat::ones(image_s.size(), CV_8UC1)*255
This is because Mat::ones initialize all the pixels to a value of numerical 1, Thus, we need to muliply it with 255 in order to get a pure black & white mask.
And, thanks, your issue solved my problem :)
I am using the SVM implementation of OpenCV (based on LibSVM) on iOS. Is it possible to obtain the weight vector after training?
Thank you!
After dealing with it I have been able to obtain the weights. For obtaining the weights one has to obtain first the support vectors and then add them multiplied by the alpha values.
// get the svm weights by multiplying the support vectors by the alpha values
int numSupportVectors = SVM.get_support_vector_count();
const float *supportVector;
const CvSVMDecisionFunc *dec = SVM.decision_func;
svmWeights = (float *) calloc((numOfFeatures+1),sizeof(float));
for (int i = 0; i < numSupportVectors; ++i)
{
float alpha = *(dec[0].alpha + i);
supportVector = SVM.get_support_vector(i);
for(int j=0;j<numOfFeatures;j++)
*(svmWeights + j) += alpha * *(supportVector+j);
}
*(svmWeights + numOfFeatures) = - dec[0].rho; //Be careful with the sign of the bias!
The only trick here is that the instance variable float *decision_function is protected on the opencv framework, so I had to change it in order to access it.
A cursory glance of the doc and the source code (https://github.com/Itseez/opencv/blob/master/modules/ml/src/svm.cpp) tells me that on the surface the answer is "No". The hyperplane parameters seem to be tucked away into the CvSVMSolver class. CvSVM contains an object of this class called "solver". See if you can get to its members.
Is there any built in library for sliding a window (custom size) over an image in opencv version 2.x?
I tried to write the algorithm by myself but I found it very painful and probably error-prone.
I need to slide over an image and create histogram for the input of svm.
there is one for HOG Descriptor, which calculates HOG features but I have my own feature set so I just need an algorithm to let me slide over an image.
You can define a Region of Interest (ROI) on a cv::Mat object, which gives you a new Mat object referring to the sub-window. This does not copy the underlying data, merely a new header with the appropriate metadata.
cv::Mat::operator()
See also this other question:
OpenCV C++, getting Region Of Interest (ROI) using cv::Mat
Basic code can looks like. The code is described good enought. I hope.
This is single scale slideing window 60x60 witch Step 30.
Result of this simple example is ROI.
You can visit this basic tutorial Tutorial Here.
// Parameters of your slideing window
int windows_n_rows = 60;
int windows_n_cols = 60;
// Step of each window
int StepSlide = 30;
for (int row = 0; row <= LoadedImage.rows - windows_n_rows; row += StepSlide)
{
for (int col = 0; col <= LoadedImage.cols - windows_n_cols; col += StepSlide)
{
Rect windows(col, row, windows_n_rows, windows_n_cols);
Mat Roi = LoadedImage(windows);
}
}