OpenCV error using inverse - c++

I'm working SIFT implementation using Visual C++. My code throws an error while taking inverse:
/// Load the source image
src = imread("C:/Users/Adithyaanirudhha/Documents/Visual Studio 2015/Projects/ConsoleApplication2/pa.jpg", 1);
if (display_caption("Original Image") != 0) { return 0; }
dst = src.clone();
width = src.size().width;
height = src.size().height;
Size size(height,width);
if (display_dst(DELAY_CAPTION) != 0) { return 0; }
cvtColor(src, src, CV_RGB2GRAY);
/// Applying Gaussian blur
//for(int j=0;j<4;j++)
//{
//resize(src, src, size / 2);
k = 2 ^ (1 / 2);
for(int i=0;i<3;i++)
{
//if (display_caption("Gaussian Blur") != 0) { return 0; }
GaussianBlur(src, dst, Size(), 1.6*k, 1.6*k);
if (display_dst(DELAY_BLUR*10) != 0) { return 0; }
k = k * k;
dst.copyTo(dest[m]);
//dest[m] = dst;
m++;
}
//}
width2 = dog[1].size().width;
height2 = dog[1].size().height;
Size sizes(width2,height2);
Mat dog_inv(sizes,0,CV_64F);
for (int n = 0; n < 2; n++)
{
if(m1!=3 || m1 != 6 || m1 != 9)
subtract(dest[m1 + 1], dest[m1], dog[n],noArray(),-1);
}
for (int i = 0; i < 2; i++)
{
Sobel(dog[i], grad_x, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(grad_x, grad_x);
transpose(grad_x, temp);
Sobel(dog[i], grad_x_2, CV_16S, 2, 0, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(grad_x_2, grad_x_2);
c = invert(dog[i],dog_inv, DECOMP_LU);
Sobel(dog[i], grad_x_2_1, CV_16S, 2, 0, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(grad_x_2_1, grad_x_2_1);
//imshow(window_name,src);
//grad_x_2_1 = grad_x_2_1.inv(CV_32F);
multiply(grad_x_2_1, grad_x, x_max, 1, 1);
multiply(temp, x_max, p1, 1, 1);
transpose(x_max,temp);
//multiply(temp, grad_x_2, p2, 1, 1);
multiply(p2, x_max, p2, 1, 1);
imshow(window_name, dog[1]);
/*for (int y = 0; y < dog[i].rows; y++)
{
for (int x = 0; x < dog[i].cols; x++)
{
dog[i].at<Vec3b>(y, x) = (-1 * (p1.at<Vec3b>(y, x)) + 0.5*(p2.at<Vec3b>(y, x)) + dog[i].at<Vec3b>(y, x));
}
}*/
//imshow(window_name, dog[1]);
//imshow(window_name, src);
and the error is:
OpenCV Error: Assertion failed (type == CV_32F || type == CV_64F) in cv::invert,
file C:\buildslave64\win64_amdocl\master_PackSlave-win64-vc14-shared\opencv\mod
ules\core\src\lapack.cpp, line 798
Press any key to continue . . .

OpenCV Error: Assertion failed (type == CV_32F || type == CV_64F) in cv::invert
means that you need to pass to invert a matrix of type CV_32F (float) or CV_64F (double). But you're passing a CV_16S (short), because you set this when calling:
Sobel(dog[i], grad_x, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);
^^^^^^
So you can
change the type of the matrix returned by Sobel to CV_32F
Sobel(dog[i], grad_x, CV_32F, 1, 0, 3, 1, 0, BORDER_DEFAULT);
c = invert(dog[i],dog_inv, DECOMP_LU);
or convert the matrix you pass to invert to the correct type
Sobel(dog[i], grad_x, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);
Mat tmp;
dog[i].convertTo(tmp, CV_32F);
c = invert(tmp,dog_inv, DECOMP_LU);

Related

How to distinguish circle from other shapes by using OpenCV?

I am fairly newbie in OpenCV and C++.
And I am stuck at the problem , which might seem like a fairly trivial.
I am trying to distinguish circle from other shapes, such as rectagular, square, triangle, and etc...
This is the code below what I use
void setLabel(Mat& image, string str, vector<Point> contour){
int fontface = FONT_HERSHEY_SIMPLEX;
double scale = 0.5;
int thickness = 1;
int baseline = 0;
Size text = getTextSize(str, fontface, scale, thickness, &baseline);
Rect r = boundingRect(contour);
Point pt(r.x + ((r.width - text.width) / 2), r.y + ((r.height + text.height) / 2));
rectangle(image, pt + Point(0, baseline), pt + Point(text.width, -text.height), CV_RGB(200, 200, 200), CV_FILLED);
putText(image, str, pt, fontface, scale, CV_RGB(0, 0, 0), thickness, 8);
}
int main(){
Mat img_input, img_result, img_gray;
String filepath("C:\\Users\\PC\\Desktop\\kist\\test.png");
img_input = imread(filepath, IMREAD_COLOR);
if (img_input.empty()){
cout << "Could not open or find the image" << std::endl;
return -1;
}
cvtColor(img_input, img_gray, COLOR_BGR2GRAY);
medianBlur(img_gray, img_gray, 5);
vector <Vec3f> circles;
HoughCircles(img_gray, circles, CV_HOUGH_GRADIENT, 1, 20, 200, 50, 0, 0);
threshold(img_gray, img_gray, 125, 255, THRESH_BINARY_INV | THRESH_OTSU);
vector<vector<Point> > contours;
findContours(img_gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
vector<Point2f> approx;
img_result = img_input.clone();
for (size_t i = 0; i < contours.size(); i++){
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
if (fabs(contourArea(Mat(approx))) > 0){
int size = approx.size();
if (size % 2 == 0) {
line(img_result, approx[0], approx[approx.size() - 1], Scalar(0, 255, 0), 2);
for (int k = 0; k < size - 1; k++)
line(img_result, approx[k], approx[k + 1], Scalar(0, 255, 0), 2);
for (int k = 0; k < size; k++)
circle(img_result, approx[k], 3, Scalar(0, 0, 255));
for (size_t j = 0; j < circles.size(); j++) {
Vec3i c = circles[j];
Point center = Point(c[0], c[1]);
circle(img_result, center, 2, Scalar(0, 255, 0), 2, LINE_AA);
int radius = c[2];
circle(img_result, center, radius, Scalar(0, 255, 0), 2, LINE_AA);
}
}
else if (size % 2 > 0) {
line(img_result, approx[0], approx[approx.size() - 1], Scalar(0, 255, 0), 2);
for (int k = 0; k < size - 1; k++)
line(img_result, approx[k], approx[k + 1], Scalar(0, 255, 0), 2);
for (int k = 0; k < size; k++)
circle(img_result, approx[k], 3, Scalar(0, 0, 255));
}
if (size == 3)
setLabel(img_result, "triangle", contours[i]);
else if (size == 4 && isContourConvex(Mat(approx)))
setLabel(img_result, "rectangle", contours[i]);
else if (size == 5 && isContourConvex(Mat(approx)))
setLabel(img_result, "pentagon", contours[i]);
else if (size == 6 && isContourConvex(Mat(approx)))
setLabel(img_result, "hexagon", contours[i]);
else if (size == 10 && isContourConvex(Mat(approx)))
setLabel(img_result, "decagon", contours[i]);
else {
setLabel(img_result, to_string(approx.size()), contours[i]);
}
}
else if (fabs(contourArea(Mat(approx))) == 0) {
for (size_t i = 0; i < circles.size(); i++) {
Vec3i c = circles[i];
Point center = Point(c[0], c[1]);
circle(img_result, center, 2, Scalar(0, 100, 100), 2, LINE_AA);
int radius = c[2];
circle(img_result, center, radius, Scalar(255, 0, 255), 2, LINE_AA);
}
setLabel(img_result, to_string(approx.size()), contours[i]);
}
}
imshow("input", img_input);
imshow("result", img_result);
And as shown in the figure below, I was able to find out vertex of each figure and draw lines.
However, I want to remove the vertex and straight lines and leave the circle outline from circle shape. And further, I would like to describe the circle shape as 'circle' and count the number of each shape.
Please help me ~~
Thanks a ton !!
enter image description here

smoothing a contour for hand using OpenCV in C++

I have this code but my contours for hand are not smooth. How can I fix it?
void Hand::analyzeHand(cv::Mat xyzMap)
{
cv::Mat normalizedDepthMap;
cv::Mat channel[3];
cv::split(xyzMap, channel);
cv::normalize(channel[2], normalizedDepthMap, 0, 255, cv::NORM_MINMAX, CV_8UC1);
// Resize input
cv::Mat input;
cv::pyrUp(normalizedDepthMap, input, cv::Size(normalizedDepthMap.cols * 2, normalizedDepthMap.rows * 2));
cv::pyrUp(input, input, cv::Size(input.cols * 2, input.rows * 2));
cv::Mat threshold_output;
std::vector< std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
// Find contours
cv::threshold(input, threshold_output, 100, 255, cv::THRESH_BINARY);
cv::findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
// Find contour polygon
std::vector< std::vector< cv::Point> > contours_poly(contours.size());
for (auto i = 0; i < contours.size(); i++)
{
cv::approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 3, true);
}
// Find largest contour
auto contour = Hand::findComplexContour(contours);
// Find approximated convex hull
std::vector<cv::Point> hull;
std::vector<cv::Point> completeHull;
std::vector<int> indexHull;
if (contour.size() > 1)
{
cv::convexHull(contour, completeHull, false, true);
cv::convexHull(contour, indexHull, false, false);
hull = Hand::clusterConvexHull(completeHull, Hand::CLUSTER_THRESHOLD);
}
// Find convexityDefects
std::vector<cv::Vec4i> defects;
if (indexHull.size() > 3)
{
cv::convexityDefects(contour, indexHull, defects);
}
// Find max and min distances
double minVal, maxVal;
cv::Point minLoc, maxLoc;
cv::minMaxLoc(channel[2], &minVal, &maxVal, &minLoc, &maxLoc);
// Find center of contour
auto center = Hand::findCenter(contour);
centroid_xyz = xyzMap.at<cv::Vec3f>(center.y / 4, center.x / 4);
centroid_ij = cv::Point2i(center.x, center.y); // SCALING
// Generate visual
cv::Mat img = cv::Mat::zeros(input.rows, input.cols, CV_8UC3);
auto color = cv::Scalar(0, 255, 0);
// Draw contours
cv::circle(img, center, 5, cv::Scalar(255, 0, 0), 2);
for (auto i = 0; i < contours.size(); i++)
{
cv::drawContours(img, contours_poly, i, color, 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point());
}
// Draw hull
cv::Point index;
cv::Point index_right;
cv::Point index_left;
double farthest = 0;
if (hull.size() > 1)
{
for (auto i = 0; i < hull.size(); i++)
{
auto p1 = hull[i];
auto p2 = hull[(i + 1) % hull.size()];
//cv::line(img, p1, p2, cv::Scalar(255, 0, 0), 1);
if (p1.y < centroid_ij.y && Util::euclideanDistance2D(p1, centroid_ij) > farthest)
{
farthest = Util::euclideanDistance2D(p1, centroid_ij);
index = p1;
index_right = hull[(i + 1) % hull.size()];
index_left = hull[(i - 1) % hull.size()];
}
}
}
// Draw defects (filter)
std::vector<cv::Point> endpoints;
std::vector<cv::Point> fingerDefects;
cv::Point lastStart;
auto found = -1;
for (auto i = 0; i < defects.size(); i++)
{
auto defect = defects[i];
auto start = contour[defect[0]];
auto end = contour[defect[1]];
auto farPt = contour[defect[2]];
// Depth from edge of contour
// std::cout << "Depth: " << depth << "\tThreshold: " << cv::norm(maxLoc - center) << "\t";
// Defect conditions: depth is sufficient, inside contour, y value is above center
auto depth = defect[3];
// maxLoc largest depth
// first condition replace with meters distance from the edge
// second test if inside the hull (no change)
// above the center (no change)
if (cv::norm(maxLoc - center) * 15 < depth && cv::pointPolygonTest(hull, farPt, false) > 0 && farPt.y < center.y)
{
auto pt1 = xyzMap.at<cv::Vec3f>(farPt.y / 4, farPt.x / 4);
if (Util::euclidianDistance3D(pt1, centroid_xyz) > 0.05)
{
endpoints.push_back(start);
endpoints.push_back(end);
fingerDefects.push_back(farPt);
}
}
}
// Cluster fingertip locations
endpoints = Hand::clusterConvexHull(endpoints, Hand::CLUSTER_THRESHOLD);
for (auto i = 0; i < endpoints.size(); i++)
{
auto endpoint = endpoints[i];
cv::Point closestDefect;
auto minDefectDistance = 1 << 29;
for (auto j = 0; j < fingerDefects.size(); j++)
{
if (cv::norm(endpoint - fingerDefects[j]) < minDefectDistance)
{
minDefectDistance = cv::norm(endpoint - fingerDefects[j]);
closestDefect = fingerDefects[j];
}
}
auto endPoint_xyz = Util::averageAroundPoint(xyzMap, cv::Point2i(endpoint.x / 4, endpoint.y / 4), 10);
auto closestDefect_xyz = Util::averageAroundPoint(xyzMap, cv::Point2i(closestDefect.x / 4, closestDefect.y / 4), 10);
auto finger_length = Util::euclidianDistance3D(endPoint_xyz, closestDefect_xyz);
if (finger_length < 0.08 && finger_length > 0.025 && endpoint.y < closestDefect.y)
{
fingers_xyz.push_back(endPoint_xyz);
fingers_ij.push_back(cv::Point2i(endpoint.x, endpoint.y)); // SCALING
defects_xyz.push_back(Util::averageAroundPoint(xyzMap, cv::Point2i(closestDefect.x / 4, closestDefect.y / 4), 5));
defects_ij.push_back(cv::Point2i(closestDefect.x, closestDefect.y)); // SCALING
}
}
if (static_cast<float>(cv::countNonZero(channel[2])) / (xyzMap.rows*xyzMap.cols) > 0.3)
{
return;
}
// If there is one or less visible fingers
if (fingers_xyz.size() <= 1)
{
fingers_xyz.clear();
fingers_ij.clear();
auto indexFinger = Util::averageAroundPoint(xyzMap, cv::Point2i(index.x / 4, index.y / 4), 10);
fingers_xyz.push_back(indexFinger);
fingers_ij.push_back(cv::Point2i(index.x, index.y)); // SCALING
auto angle = Util::TriangleAngleCalculation(index_left.x, index_left.y, index.x, index.y, index_right.x, index_right.y);
if (defects_ij.size() != 0)
{
for (auto i = 0; i < fingers_xyz.size(); i++)
{
cv::circle(img, fingers_ij[i], 5, cv::Scalar(0, 0, 255), 3);
cv::line(img, defects_ij[i], fingers_ij[i], cv::Scalar(255, 0, 255), 2);
cv::circle(img, defects_ij[i], 5, cv::Scalar(0, 255, 255), 2);
cv::line(img, defects_ij[i], centroid_ij, cv::Scalar(255, 0, 255), 2);
}
}
else if (angle > ANGLE_THRESHHOLD)
{
cv::circle(img, fingers_ij[0], 5, cv::Scalar(0, 0, 255), 3);
cv::line(img, fingers_ij[0], centroid_ij, cv::Scalar(255, 0, 255), 2);
}
}
else {
for (auto i = 0; i < fingers_xyz.size(); i++)
{
cv::circle(img, fingers_ij[i], 5, cv::Scalar(0, 0, 255), 3);
cv::line(img, defects_ij[i], fingers_ij[i], cv::Scalar(255, 0, 255), 2);
cv::circle(img, defects_ij[i], 3, cv::Scalar(0, 255, 255), 2);
cv::line(img, defects_ij[i], centroid_ij, cv::Scalar(255, 0, 255), 2);
}
}
if (camera_name == "sr300")
{
cv::Mat img_dst;
cv::resize(img, img_dst, cv::Size(640, 489), 0, 0, cv::INTER_AREA);
cv::namedWindow("Contours", CV_WINDOW_AUTOSIZE);
cv::imshow("Contours", img_dst);
}
else
{
cv::namedWindow("Contours", CV_WINDOW_AUTOSIZE);
cv::imshow("Contours", img);
}
}
This is what I get:
additionally, I read in a book this is a good idea to use the following formula for epsilon but doesn't work well at all
cv::approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 0.01*cv::arcLength(cv::Mat(contours[i]), true), true);

How to implement Filter2d Opencv in C++ without the builtin function? [duplicate]

I have been tasked with making my own Sobel method, and not use the cv::Sobel found in OpenCV.
I tried implementing one I found at Programming techniques
When I run the program, cv::Mat throws an error, however. Anyone have any idea why?
Sobel method:
int sobelCorrelation(Mat InputArray, int x, int y, String xory)
{
if (xory == "x") {
return InputArray.at<uchar>(y - 1, x - 1) +
2 * InputArray.at<uchar>(y, x - 1) +
InputArray.at<uchar>(y + 1, x - 1) -
InputArray.at<uchar>(y - 1, x + 1) -
2 * InputArray.at<uchar>(y, x + 1) -
InputArray.at<uchar>(y + 1, x + 1);
}
else if (xory == "y")
{
return InputArray.at<uchar>(y - 1, x - 1) +
2 * InputArray.at<uchar>(y - 1, x) +
InputArray.at<uchar>(y - 1, x + 1) -
InputArray.at<uchar>(y + 1, x - 1) -
2 * InputArray.at<uchar>(y + 1, x) -
InputArray.at<uchar>(y + 1, x + 1);
}
else
{
return 0;
}
}
Calling and processing it in another function:
void imageOutput(Mat image, String path) {
image = imread(path, 0);
Mat dst;
dst = image.clone();
int sum, gx, gy;
if (image.data && !image.empty()){
for (int y = 0; y < image.rows; y++)
for (int x = 0; x < image.cols; x++)
dst.at<uchar>(y, x) = 0.0;
for (int y = 1; y < image.rows - 1; ++y) {
for (int x = 1; x < image.cols - 1; ++x){
gx = sobelCorrelation(image, x, y, "x");
gy = sobelCorrelation(image, x, y, "y");
sum = absVal(gx) + absVal(gy);
if (sum > 255)
sum = 255;
else if (sum < 0)
sum = 0;
dst.at<uchar>(x, y) = sum;
}
}
namedWindow("Original");
imshow("Original", image);
namedWindow("Diagonal Edges");
imshow("Diagonal Edges", dst);
}
waitKey(0);
}
Main:
int main(int argc, char* argv[]) {
Mat image;
imageOutput(image, "C:/Dropbox/2-falling-toast-ted-kinsman.jpg");
return 0;
}
The absVal method:
int absVal(int v)
{
return v*((v < 0)*(-1) + (v > 0));
}
When run it throws this error:
Unhandled exception at 0x00007FFC9365A1C8 in Miniproject01.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000A780A4F110.
and points to here:
template<typename _Tp> inline
_Tp& Mat::at(int i0, int i1)
{
CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] &&
(unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()) &&
CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
return ((_Tp*)(data + step.p[0] * i0))[i1];
}
If anyone have any advice or ideas what I am doing wrong it would be greatly appreciated!
This code snippet is to demonstrate how to compute Sobel 3x3 derivatives convolving the image with Sobel kernels. You can easily extend to different kernel sizes giving the kernel radius as input to my_sobel, and creating the appropriate kernel.
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
void my_sobel(const Mat1b& src, Mat1s& dst, int direction)
{
Mat1s kernel;
int radius = 0;
// Create the kernel
if (direction == 0)
{
// Sobel 3x3 X kernel
kernel = (Mat1s(3,3) << -1, 0, +1, -2, 0, +2, -1, 0, +1);
radius = 1;
}
else
{
// Sobel 3x3 Y kernel
kernel = (Mat1s(3, 3) << -1, -2, -1, 0, 0, 0, +1, +2, +1);
radius = 1;
}
// Handle border issues
Mat1b _src;
copyMakeBorder(src, _src, radius, radius, radius, radius, BORDER_REFLECT101);
// Create output matrix
dst.create(src.rows, src.cols);
// Convolution loop
// Iterate on image
for (int r = radius; r < _src.rows - radius; ++r)
{
for (int c = radius; c < _src.cols - radius; ++c)
{
short s = 0;
// Iterate on kernel
for (int i = -radius; i <= radius; ++i)
{
for (int j = -radius; j <= radius; ++j)
{
s += _src(r + i, c + j) * kernel(i + radius, j + radius);
}
}
dst(r - radius, c - radius) = s;
}
}
}
int main(void)
{
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Compute custom Sobel 3x3 derivatives
Mat1s sx, sy;
my_sobel(img, sx, 0);
my_sobel(img, sy, 1);
// Edges L1 norm
Mat1b edges_L1;
absdiff(sx, sy, edges_L1);
// Check results against OpenCV
Mat1s cvsx,cvsy;
Sobel(img, cvsx, CV_16S, 1, 0);
Sobel(img, cvsy, CV_16S, 0, 1);
Mat1b cvedges_L1;
absdiff(cvsx, cvsy, cvedges_L1);
Mat diff_L1;
absdiff(edges_L1, cvedges_L1, diff_L1);
cout << "Number of different pixels: " << countNonZero(diff_L1) << endl;
return 0;
}
If i were you, i would almost always avoid using for loops(if possible). Unnecessary for loops tend to slow down the execution. Instead, reuse wherever possible. For example, the code below uses filter2D give 2d Correlation result:
Mat kern = (Mat_<float>(3,3)<<-1,0,1,-2,0,2,-1,0,1);
Mat dest;
cv::filter2D(src,dest,src.type(),kern);
If you would like to get convolution results, you would need to flip the kernel 'kern' before filtering.
cv::flip(kern,kern, -1);
If you would like to squeeze more performance, you can use separable filters 'sepFilter2D'.
thanks for the post,
I was able to generate gradiant map using the above kernel, and using openCV code filter2D getting from
Using custom kernel in opencv 2DFilter - causing crash ... convolution how?
to convolve the image with the kernel. the code that I used is
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
//Loading the source image
Mat src;
//src = imread("1.png");
src = cv::imread("E:\\Gray_Image.bmp", 0);
//Output image of the same size and the same number of channels as src.
Mat dst1,dst2,grad;
//Mat dst = src.clone(); //didn't help...
//desired depth of the destination image
//negative so dst will be the same as src.depth()
int ddepth = -1;
//the convolution kernel, a single-channel floating point matrix:
//Mat kernel = imread("kernel.png");
Mat kernel_x = (Mat_<float>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
Mat kernel_y = (Mat_<float>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
kernel_x.convertTo(kernel_x, CV_32F); kernel_y.convertTo(kernel_y, CV_32F); //<<not working
//normalize(kernel, kernel, 1.0, 0.0, 4, -1, noArray()); //doesn't help
//cout << kernel.size() << endl; // ... gives 11, 11
//however, the example from tutorial that does work:
//kernel = Mat::ones( 11, 11, CV_32F )/ (float)(11*11);
//default value (-1,-1) here means that the anchor is at the kernel center.
Point anchor = Point(-1, -1);
//value added to the filtered pixels before storing them in dst.
double delta = 0;
//alright, let's do this...
filter2D(src, dst1, ddepth, kernel_x, anchor, delta, BORDER_DEFAULT);
filter2D(src, dst2, ddepth, kernel_y, anchor, delta, BORDER_DEFAULT);
imshow("Source", src); //<< unhandled exception here
//imshow("Kernel1", kernel_x); imshow("Kernel2", kernel_y);
imshow("Destination1", dst1);
imshow("Destination2", dst2);
addWeighted(dst1, 0.5, dst2, 0.5, 0, grad);
imshow("Destination3", grad);
waitKey(1000000);
return 0;
}

SVM training issue for a simple dataset (Opencv 2.4.9)

I'm trying a simple example to learn SVM in OpenCV, I'm not getting the right support vectors after training. Need some help in understanding the issue.
My code is :
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
using namespace cv;
using namespace std;
int main() {
Mat frame(Size(640,360), CV_8UC3, Scalar::all(255));
float train[15][2] = { {296, 296}, {296, 312}, {312, 8}, {312, 56}, {312, 88}, {328, 88}, {328, 104}, {328, 264}, {344, 8}, {344, 40}, {360, 8}, {360, 56}, {376, 8}, {376, 40}, {376, 56} };
Mat trainingDataMat(15, 2, CV_32FC1, train);
float labels[15] = { -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1 };
Mat labelsMat(15, 1, CV_32FC1, labels);
CvSVMParams param;
param.svm_type = CvSVM::C_SVC;
param.C = 0.1;
param.kernel_type = SVM::LINEAR;
param.term_crit = TermCriteria(CV_TERMCRIT_ITER, 1000, 1e-6);
CvSVM SVM;
SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), param);
cout<< "Training Finished..." << endl;
for(int i = 0; i < frame.rows; ++i) {
for(int j = 0; j < frame.cols; ++j) {
Mat sampleMat = (Mat_<float>(1,2) << i,j);
float response = SVM.predict(sampleMat);
//cout << response << endl;
if(response == 1) {
frame.at<Vec3b>(i,j)[2] = 0;
} else {
frame.at<Vec3b>(i,j)[0] = 0;
}
}
}
for(int dis = 0; dis < trainingDataMat.rows; dis++) {
if(labels[dis] == 1) {
circle(frame, Point((int)train[dis][0], (int)train[dis][1]), 3, Scalar (0, 0, 0), -1);
} else {
circle(frame, Point((int)train[dis][0], (int)train[dis][1]), 3, Scalar (0, 255, 0), -1);
}
}
int n = SVM.get_support_vector_count();
for(int i = 0; i < n; i++) {
const float* v = SVM.get_support_vector(i);
cout << "support Vectors : " << v[0] << " " << v[1] <<endl;
circle(frame,Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), 2, 8);
}
imwrite("frame.jpg",frame);
imshow("output", frame);
waitKey(0);
return 0;
}
Output image is attached
The SVM line is not separating the two classes as I expect.
Result for Support Vector is
support Vectors : 0 0.0125
The SVM should be OK. I think the problem lies in your display. When you call your circle(frame, Point((int)train[dis][0], (int)train[dis][1]), 3, Scalar (0, 0, 0), -1);, OpenCV understands that you want a circle in row number train[dis][1] and column number train[dis][0]. This is not what you want because a specificity of OpenCV is that it uses different coordinate systems for matrices and points. image.at<float>(Point(i,j)) is equivalent to image.at<float>(j,i).
Try replacing your circle calls with this:
if(labels[dis] == 1) {
circle(frame, Point((int)train[dis][1], (int)train[dis][0]), 3, Scalar (0, 0, 0), -1);
} else {
circle(frame, Point((int)train[dis][1], (int)train[dis][0]), 3, Scalar (0, 255, 0), -1);
}

convolution using DFT

im using the following code to calculate convolution of an image with a specified kernel(in my case gaussian). Everytime I get a different result and the result image is not even close to the one i obtained by convolution in the Spatial domain. First I thought the problem is with the datatype of the images. I changed them to 32 and 64 but still the same results. Can anyone tell me what could be wrong?
http://opencv.willowgarage.com/documentation/cpp/core_operations_on_arrays.html#dft
this function above is giving me a black image. I have input in GRAYSCALE.
void convol_fft(const Mat& A,const vector<vector<float>>& kernel2d,Mat& result)
{
Mat B = Mat(3,3,CV_64F);
for (int row = 0; row < kernel2d.size(); row++)
for (int col = 0; col < kernel2d[row].size(); col++){
B.at<uchar>(row,col) = (uchar)kernel2d[row][col];
}
int dft_M = getOptimalDFTSize( A.rows+B.rows-1 );
int dft_N = getOptimalDFTSize( A.cols+B.cols-1 );
Mat dft_A = Mat::zeros(dft_M, dft_N, CV_64F);
Mat dft_B = Mat::zeros(dft_M, dft_N, CV_64F);
Mat dft_A_part = dft_A(Rect(0, 0, A.cols,A.rows));
A.convertTo(dft_A_part, dft_A_part.type(), 1, -mean(A)[0]);
Mat dft_B_part = dft_B(Rect(0, 0, B.cols,B.rows));
B.convertTo(dft_B_part, dft_B_part.type(), 1, -mean(B)[0]);
dft(dft_A, dft_A, 0, A.rows);
dft(dft_B, dft_B, 0, B.rows);
// set the last parameter to false to compute convolution instead of correlation
mulSpectrums( dft_A, dft_B, dft_A, 0, false );
idft(dft_A, dft_A, DFT_SCALE, A.rows + B.rows - 1 );
result = dft_A(Rect(0, 0, A.cols + B.cols - 1, A.rows + B.rows - 1));
normalize(result, result, 0, 1, NORM_MINMAX, result.type());
pow(result, 3., result);
// B ^= Scalar::all(255);
}
The following code based on openCV's phaseCorrelateRes() will do correlation in 2 dimensions.
static void fftShift(InputOutputArray _out)
{
Mat out = _out.getMat();
if(out.rows == 1 && out.cols == 1)
{
// trivially shifted.
return;
}
vector<Mat> planes;
split(out, planes);
int xMid = out.cols >> 1;
int yMid = out.rows >> 1;
bool is_1d = xMid == 0 || yMid == 0;
if(is_1d)
{
xMid = xMid + yMid;
for(size_t i = 0; i < planes.size(); i++)
{
Mat tmp;
Mat half0(planes[i], Rect(0, 0, xMid, 1));
Mat half1(planes[i], Rect(xMid, 0, xMid, 1));
half0.copyTo(tmp);
half1.copyTo(half0);
tmp.copyTo(half1);
}
}
else
{
for(size_t i = 0; i < planes.size(); i++)
{
// perform quadrant swaps...
Mat tmp;
Mat q0(planes[i], Rect(0, 0, xMid, yMid));
Mat q1(planes[i], Rect(xMid, 0, xMid, yMid));
Mat q2(planes[i], Rect(0, yMid, xMid, yMid));
Mat q3(planes[i], Rect(xMid, yMid, xMid, yMid));
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
}
}
merge(planes, out);
}
void Correlate2d(
const cv::Mat& src1,
const cv::Mat& src2,
cv::Mat& dst,
double* response)
{
CV_Assert( src1.type() == src2.type());
CV_Assert( src1.type() == CV_32FC1 || src1.type() == CV_64FC1 );
CV_Assert( src1.size == src2.size);
int M = getOptimalDFTSize(src1.rows);
int N = getOptimalDFTSize(src1.cols);
Mat padded1, padded2, paddedWin;
if(M != src1.rows || N != src1.cols)
{
copyMakeBorder(src1, padded1, 0, M - src1.rows, 0, N - src1.cols, BORDER_CONSTANT, Scalar::all(0));
copyMakeBorder(src2, padded2, 0, M - src2.rows, 0, N - src2.cols, BORDER_CONSTANT, Scalar::all(0));
}
else
{
padded1 = src1;
padded2 = src2;
}
Mat FFT1, FFT2, P, Pm, C;
// correlation equation
// Reference: http://en.wikipedia.org/wiki/Phase_correlation
dft(padded1, FFT1, DFT_REAL_OUTPUT);
dft(padded2, FFT2, DFT_REAL_OUTPUT);
mulSpectrums(FFT1, FFT2, dst, 0, true);
idft(dst, dst, DFT_SCALE); // gives us the correlation result...
fftShift(dst); // shift the energy to the center of the frame.
// locate the highest peak
Point peakLoc;
minMaxLoc(dst, NULL, NULL, NULL, &peakLoc);
// max response is scaled
if( response )
*response = dst.at<float>(peakLoc);
}
You can find the code in \opencv\sources\modules\imgproc\src\phasecorr.cpp
In order to change the code to convolution simply change this line:
mulSpectrums(FFT1, FFT2, dst, 0, true);
to
mulSpectrums(FFT1, FFT2, dst, 0, false);
This is equivalent to doing in matlab:
dst = fftshift(ifft2(fft2(src1).*conj(fft2(src2))))
I am not sure about OpenCV...but this looks suspicious.
for (int row = 0; row < kernel2d.size(); row++)
for (int col = 0; col < kernel2d[row].size(); col++){
B.at<uchar>(row,col) = (uchar)kernel2d[row][col];
}
If you are filling up the B kernel then the row should be kernel2d[col].size(). It looks like you are overrunning the B kernel. What is value of kernel2d.size() ?
Why not just load the values directly? Saving all the function calls.
For gaussian kernel it should look something like {1,2,1,2,3,2,1,2,1}.