When I call the function cvGoodFeaturesToTrack to find Harris corners I get this error:
OpenCV Error: Assertion failed (src.type() == CV_8UC1 || src.type() == CV_32FC1) in cornerEigenValsVecs, file /build/buildd/opencv-2.1.0/src/cv/cvcorner.cpp,line 254
terminate called after throwing an instance of 'cv::Exception'
what(): /build/buildd/opencv-2.1.0/src/cv/cvcorner.cpp:254: error: (-215) src.type() == CV_8UC1 || src.type() == CV_32FC1 in function cornerEigenValsVecs
Aborted
It compiles correctly but when I try to run it, it gives me that error.
Here is the code:
IplImage* eig_image = 0;
IplImage* temp_image = 0;
IplImage *img1 = 0;
img1 = cvLoadImage("im1.pgm");
if(img1==0) {
printf("oh no!");
}
eig_image = cvCreateImage(cvGetSize(img1),IPL_DEPTH_32F, 1);
temp_image = cvCreateImage(cvGetSize(img1),IPL_DEPTH_32F, 1);
const int MAX_CORNERS = 100;
CvPoint2D32f corners[MAX_CORNERS] = {0};
int corner_count = MAX_CORNERS;
double quality_level = 0.1;
double min_distance = 1;
int eig_block_size = 3;
int use_harris = true;
double k = .4;
cvGoodFeaturesToTrack(img1, eig_image, temp_image,corners,&corner_count,quality_level,min_distance,NULL,eig_block_size,use_harris,k);
Why is this happening and how can I fix it? I appreciate any help!
OpenCV is trying to tell you that one of the images you passed to cvGoodFeaturesToTrack() (the error is actually originating in the helper function cornerEigenValsVecs()) is not of the required type CV_8UC1 or CV_32FC1.
I suspect img1 may not be of the type you need it to be. What is the type of the img1 matrix? If it is color, then it may be of type CV_8UC3. Consider using cvCvtColor to make it a grayscale image.
Or, alternatively you can initially load the image as grayscale like:
cvLoadImage("im1.pgm", CV_LOAD_IMAGE_GRAYSCALE);
Related
I'm not familiar with opencv, but I need to use the function ‘remap’ to rectify the image.
I have an image with 960x1280, and a remap file called ‘remap.bin’ with 9.8MB(is equaled to 960x1280x4x2, which means the two floats in one position(x,y));
Applies a generic geometrical transformation to an image.
C++: void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
map1 – The first map of either (x,y) points or just x values having the type CV_16SC2 , CV_32FC1 , or CV_32FC2 . See convertMaps() for details on converting a floating point representation to fixed-point for speed.
map2 – The second map of y values having the type CV_16UC1 , CV_32FC1 , or none (empty map if map1 is (x,y) points), respectively.
According to the explain,
I code like this:
int main(int argc, char* argv[]){
if(argc != 3){
printf("Please enter one path of image and one path of mapdata!\n");
return 0;
}
std::string image_path = argv[1];
char* remap_path = argv[2];
cv::Mat src = cv::imread(image_path);
cv::Mat dst;
dst.create( src.size(), src.type());
cv::Mat map2;
map2.create( src.size(), CV_32FC1);
map2.data = NULL;
cv::Mat mapXY;
mapXY.create( src.rows, src.cols, CV_64FC1);
FILE *fp;
fp = fopen(remap_path, "rb");
fread(mapXY.data, sizeof(float), mapXY.cols*mapXY.rows*2, fp);
fclose(fp);
imshow("src", src);
printf("remap!\n");
cv::remap(src, dst, mapXY, map2, cv::INTER_LINEAR);
imshow("dst", dst);
cv::waitKey(0);
return 0;
But when I run the program I get this error:
OpenCV Error: Assertion failed (((map1.type() == CV_32FC2 || map1.type() == CV_16SC2) && !map2.data) || (map1.type() == CV_32FC1 && map2.type() == CV_32FC1)) in remap, file /home/liliming/opencv-2.4.13/modules/imgproc/src/imgwarp.cpp, line 3262 terminate called after throwing an instance of 'cv::Exception' what(): /home/liliming/opencv-2.4.13/modules/imgproc/src/imgwarp.cpp:3262: error: (-215) ((map1.type() == CV_32FC2 || map1.type() == CV_16SC2) && !map2.data) || (map1.type() == CV_32FC1 && map2.type() == CV_32FC1) in function remap Aborted (core dumped)
I have no idea about it.
Could anyone help me? or give some sample codes?
Thank you very much!
The documentation for OpenCV 3.1 says:
map1 The first map of either (x,y) points or just x values having the type
CV_16SC2 , CV_32FC1, or CV_32FC2.
The assert says that map1 doesn't have a type of CV_32FC2
This is because you are creating and reading it with a type of CV_64FC1.
You need to convert it to the correct type: array of two dimensions of type CV_32FC2 (two 32-bit floats per element.)
The documentation goes on to say:
See `convertMaps` for details on converting a
floating point representation to fixed-point for speed.
Documentation can be found here: https://docs.opencv.org/3.1.0/da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4
I separate the remap table into two tables remapX, remapY.
Like this:
float *data_xy = (float *)malloc(sizeof(float)*960*1280*2);
FILE *fp;
fp = fopen(remap_path, "rb");
fread(data_xy, sizeof(float), 960*1280*2, fp);
fclose(fp);
for(int y=0; y<1280; ++y){
for(int x=0; x<960; ++x){
map_x.at<float>(y, x) = data_xy[(y*960+x)*2];
map_y.at<float>(y, x) = data_xy[(y*960+x)*2+1];
}
}
And then use the
cv::remap(src, dst, map_x, map_y, cv::INTER_LINEAR);
It works well.
But I don't know how to use one parameter map1 to finish remap.
I was trying to write Point2f imagePoints to a Mat image in openCV. I was following the link below.
Create Mat from vector<point2f>
But I am getting 'Assertion failed' error. Please help.
Code:
std::vector<cv::Point3d> objectPoints;
std::vector<cv::Point2d> imagePoints;
cv::Mat intrisicMat(3, 3, cv::DataType<double>::type);
intrisicMat.at<double>(0, 0) = param.focalLength.first;
intrisicMat.at<double>(0, 1) = 0;
intrisicMat.at<double>(0, 2) = param.principalPoint.first;
intrisicMat.at<double>(1, 0) = 0;
intrisicMat.at<double>(1, 1) = param.focalLength.second;
intrisicMat.at<double>(1, 2) = param.principalPoint.second;
intrisicMat.at<double>(2, 0) = 0;
intrisicMat.at<double>(2, 1) = 0;
intrisicMat.at<double>(2, 2) = 1;
cv::Mat rVec(3, 1, cv::DataType<double>::type); // Rotation vector
rVec.at<double>(0) = 0;
rVec.at<double>(1) = 0;
rVec.at<double>(2) = 0;
cv::Mat tVec(3, 1, cv::DataType<double>::type); // Translation vector
tVec.at<double>(0) = 0;
tVec.at<double>(1) = 0;
tVec.at<double>(2) = 0;
cv::Mat distCoeffs(5, 1, cv::DataType<double>::type); // Distortion vector
distCoeffs.at<double>(0) = param.distortionRadial.at(0);
distCoeffs.at<double>(1) = param.distortionRadial.at(1);
distCoeffs.at<double>(2) = param.distortionTangential.first;
distCoeffs.at<double>(3) = param.distortionTangential.second;
distCoeffs.at<double>(4) = param.distortionRadial.at(2);
projectPoints(objectPoints, rVec, tVec, intrisicMat, distCoeffs, imagePoints);
Mat depthImage = Mat(imagePoints);
imwrite("E:/softwares/1.8.0.71/bin/depthImage.jpg", depthImage);
cout << "depthImage.channels()=" << depthImage.channels() << endl;
Error:
OpenCV Error: Assertion failed (image.channels() == 1 || image.channels() == 3 || image.channels() == 4) in cv::imwrite_, file E:\softwares\opencv-3.1.0\opencv-3.1.0\modules\imgcodecs\src\loadsave.cpp, line 455
My image has 2 channels. So ImWrite() is throwing assertion failed error. How can I create a Mat image using the Image points if not like this?
With what you have written in the comments, it seems that you're trying to imwrite your Mat to a file. The problem is, a Mat from Vector<Point2f> will give a 2 channels matrix, which is not compatible with any image format (grayscale, RGB or RGBA).
Moreover, please edit your main post to show the code (using markdown) so it is easier to read and then help you.
In my program I have to mix the c++ and c api a bit.
I capture an image with the c api and get one frame:
CvCapture* capture = 0;
capture = cvCaptureFromCAM(0);
// some code
IplImage* image = cvQueryFrame(capture);
Then it is converted to Mat to be compatible with the new c++ api and I get a ROI:
Mat captureFrame = cvarrToMat(image);
// some code
Mat roi = captureFrame(roiRect);
At the end I have to convert the Mat back to IplImage* to work with the c api:
IplImage imgCaptureFrame = roi;
when I use this as reference &roi I get a
OpenCV Error: Assertion failed (svec[j].size == dst.size && svec[j].depth() == d
st.depth() && svec[j].channels() == 1 && i < dst.channels()) in unknown function
, file C:\slave\builds\WinInstallerMegaPack\src\opencv\modules\core\src\convert.
cpp, line 1306
in code using c api.
When I just use
IplImage imgCaptureFrame = captureFrame;
instead of
IplImage imgCaptureFrame = roi;
there isn't any error but then I don't have my roi.
What can I do to convert my roi to use it in c api?
To convert an IplImage* to cv::Mat and make an independent copy, do:
cv::Mat captureFrame = cv::Mat(image, true);
To create a ROI for captureFrame you could do something like:
cv::Rect roi;
roi.x = 165;
roi.y = 50;
roi.width = 440;
roi.height = 80;
cv::Mat cropped = new cv::Mat(captureFrame, roi);
and finally, to do the conversion the other way:
IplImage imgCaptureFrame = cropped;
I'm trying to detect whether a template image (logo) is present in a pdf document. The document can be either a scan encapsulated in a pdf or a "pure" pdf document, but this is completely random.
First, I convert the pdf document to a png image using ImageMagick's convert tool, then I cut the output images in half because they're so big, and after that I try to match a logo from a database with any of the shapes present in the half-cut image.
To do so, I use an Orb Feature Detector with an Orb Descriptor, and a RobustMatcher (sort of improved BruteForce matcher, source code available here). Here is a snippet of code from my adaptation of it :
// Read input images
Mat image1 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
Mat image2 = imread(argv[2], CV_LOAD_IMAGE_GRAYSCALE);
if (!image1.data || !image2.data) {
std::cout << " --(!) Error reading images " << std::endl;
exit(1);
}
// Setting up values for ORB Detector
int nfeatures = 800;
//float scaleFactor = 1.10;
int nlevels = 8;
int edgeThreshold = 12;
int firstLevel = 0;
int WTA_K = 2;
int scoreType = 0;
int patchSize = 31;
// Prepare the matcher
RobustMatcher rmatcher;
rmatcher.setConfidenceLevel(0.98);
rmatcher.setMinDistanceToEpipolar(1.0);
rmatcher.setRatio(0.80f);
cv::Ptr<cv::FeatureDetector> pfd = new cv::OrbFeatureDetector(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize);
rmatcher.setFeatureDetector(pfd);
cv::Ptr<cv::DescriptorExtractor> pde = new cv::OrbDescriptorExtractor();
rmatcher.setDescriptorExtractor(pde);
// Match the two images
std::vector<cv::DMatch> matches;
std::vector<cv::KeyPoint> keypoints1, keypoints2;
cv::Mat fundemental = rmatcher.match(image1, image2, matches, keypoints1, keypoints2);
// If nothing could be matched, stop here
if(matches.size() < 4){
exit(2);
}
The code works great on some examples that I chose carefully, with a highly-recognizable logo and a clean image, with certain proportions... etc. But when I try to apply the process to random pdf files, I start to get this error from OpenCV :
OpenCV Error: Assertion failed (type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U)) in batchDistance, file /home/das/Downloads/opencv-2.4.5/modules/core/src/stat.cpp, line 1797
terminate called after throwing an instance of 'cv::Exception'
what(): /home/das/Downloads/opencv-2.4.5/modules/core/src/stat.cpp:1797: error: (-215) type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U) in function batchDistance
Aborted (core dumped)
I checked for this error, and it appeared that src1.cols != src2.cols, and a quick fix for it would be to test the condition before trying to match the images. The problem is that I miss a lot of images doing so, and this would be OK only if I were working on a video stream... but I'm not, and the next image has nothing in common with the previous one, and I can't determine whether my logo was present or not in the document.
Here is the code from stat.cpp, lines 1789 to 1826 : (assertion is at the beginning on line 1797)
void cv::batchDistance( InputArray _src1, InputArray _src2,
OutputArray _dist, int dtype, OutputArray _nidx,
int normType, int K, InputArray _mask,
int update, bool crosscheck )
{
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat();
int type = src1.type();
CV_Assert( type == src2.type() && src1.cols == src2.cols &&
(type == CV_32F || type == CV_8U));
CV_Assert( _nidx.needed() == (K > 0) );
if( dtype == -1 )
{
dtype = normType == NORM_HAMMING || normType == NORM_HAMMING2 ? CV_32S : CV_32F;
}
CV_Assert( (type == CV_8U && dtype == CV_32S) || dtype == CV_32F);
K = std::min(K, src2.rows);
_dist.create(src1.rows, (K > 0 ? K : src2.rows), dtype);
Mat dist = _dist.getMat(), nidx;
if( _nidx.needed() )
{
_nidx.create(dist.size(), CV_32S);
nidx = _nidx.getMat();
}
if( update == 0 && K > 0 )
{
dist = Scalar::all(dtype == CV_32S ? (double)INT_MAX : (double)FLT_MAX);
nidx = Scalar::all(-1);
}
if( crosscheck )
{
CV_Assert( K == 1 && update == 0 && mask.empty() );
Mat tdist, tidx;
batchDistance(src2, src1, tdist, dtype, tidx, normType, K, mask, 0, false);
So I'm wondering what does this assertion mean ? What are exactly the src1 and src2 files in stat.cpp ? Why do they need to have the same number of columns ?
I tried changing to a Surf detector and extractor, but I still get the error.
If anyone has an idea, do not hesitate to post, I welcome any advice or notice !
Thanks in advance.
EDIT
I have a more precise question now : how do I ensure that src1.cols == src2.cols ? To answer that question, I think I should know what are the transformations applied to my cv::Mat image1 and image2 before batchDistance(...) is called, in order to find a condition on image1 and image2 which will ensure that src1.cols == src2.cols, so my code would look like this :
// Match the two images
std::vector<cv::DMatch> matches;
std::vector<cv::KeyPoint> keypoints1, keypoints2;
if( CONDITION_ON_IMAGE1&IMAGE2_TO_ENSURE_SRC1.COLS==SRC2.COLS ){
cv::Mat fundemental = rmatcher.match(image1, image2, matches, keypoints1, keypoints2);
}
To get rid of errors, You can play with copying and pasting the images into empty one of required size, but this is only a quick and dirty solution for the assertion.
To make detector and descriptor work properly, You might have to get to know how it works. Maybe then You will be able to get images that will work. After reading this article, it looks that ORB will have problems with scaling (they mention it in the conclusion section). This means You will need to find a workaround for it (like image pyramids, or another way to check the image at multiple scales) or use another extractor and descriptor, which is scale and rotation invariant.
I am trying to run kmeans on a 3 channel color image, but every time I try to run the function it seems to crash with the following error:
OpenCV Error: Assertion failed (data.dims <= 2 && type == CV_32F && K > 0) in unknown function, file ..\..\..\OpenCV-2.3.0\modules\core\src\matrix.cpp, line 2271
I've included the code below with some comments to help specify what is being passed in. Any help is greatly appreciated.
// Load in an image
// Depth: 8, Channels: 3
IplImage* iplImage = cvLoadImage("C:/TestImages/rainbox_box.jpg");
// Create a matrix to the image
cv::Mat mImage = cv::Mat(iplImage);
// Create a single channel image to create our labels needed
IplImage* iplLabels = cvCreateImage(cvGetSize(iplImage), iplImage->depth, 1);
// Convert the image to grayscale
cvCvtColor(iplImage, iplLabels, CV_RGB2GRAY);
// Create the matrix for the labels
cv::Mat mLabels = cv::Mat(iplLabels);
// Create the labels
int rows = mLabels.total();
int cols = 1;
cv::Mat list(rows, cols, mLabels .type());
uchar* src;
uchar* dest = list.ptr(0);
for(int i=0; i<mLabels.size().height; i++)
{
src = mLabels.ptr(i);
memcpy(dest, src, mLabels.step);
dest += mLabels.step;
}
list.convertTo(list, CV_32F);
// Run the algorithm
cv::Mat labellist(list.size(), CV_8UC1);
cv::Mat centers(6, 1, mImage.type());
cv::TermCriteria termcrit(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0);
kmeans(mImage, 6, labellist, termcrit, 3, cv::KMEANS_PP_CENTERS, centers);
The error says all: Assertion failed (data.dims <= 2 && type == CV_32F && K > 0)
These are very simple rules to understand, the function will work only if:
mImage.depth() is CV_32F
if mImage.dims is <= 2
and if K > 0. In this case, you define K as 6.
From what you stated on the question, it seems that:
IplImage* iplImage = cvLoadImage("C:/TestImages/rainbox_box.jpg");`
is loading the image as IPL_DEPTH_8U by default and not IPL_DEPTH_32F. This means that mImage is also IPL_DEPTH_8U, which is why your code is not working.