cv::cvtColor(dst,bwImage, CV_RGB2GRAY);
how can I set a specific pixel for example 0,0 value it this bwImage after usign cvtColor?
I usually use:
bwImage.at<float>(0,0) = 0;
but it now throws an exception.
OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)si
ze.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channel
s()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3
) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file C:\Users\gdarmon\Downloads
\opencv\build\include\opencv2/core/mat.hpp, line 538
Update I have found a work around
bwImage.convertTo(bwImage,CV_32F);
bwImage.at<float>(0,0)=0;
As you already found out, your black and white image does not hold floats, but 8-bit unsigned integers. Besides your workaround you could also do
bwImage.at<uint8_t>(0,0) = 0;
if you include stdint.h. As this is just a typedef for unsigned char, you can also not include the header and do this:
bwImage.at<unsigned char>(0,0) = 0;
On a side note: the default channel ordering of OpenCV is BGR, so using CV_RGB2GRAY here would be wrong, if you did not reorder the channels beforehand.
Related
[![Here is the image- skelt.tif(img)][1]][1]I am trying to find access the Mat element, angl (gradient angle). However when I use the .at statement, it throws an error.
I have already checked for NULL image (angl.data==NULL). This is not a NULL image.
Here is the code:
Mat img = imread("skelt.tif"); // this is a binary image
Mat grad_x(img.rows, img.cols, CV_16U);
Mat grad_y(img.rows, img.cols, CV_16U);
Mat angl;
Sobel(img, grad_x, CV_32F, 1, 0, 3);// Gradient X
Sobel(img,grad_y, CV_32F, 0, 1, 3); // Gradient Y
phase(grad_x, grad_y, angl,true);
cout << angl.at<float>(51, 5) << endl; // the dimensions are randomly chosen and are within the image
cout<<angl.ptr(5)[4];
The error is in the places where the .at operator is used. The error is -
OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)pt.y < (unsigned)
size.p[0] && (unsigned)(pt.x * DataType<_Tp>::channels) < (unsigned)(size.p[1] *
channels()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) &
((1 << 3) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file c:\opencv\build\in
clude\opencv2/core/mat.inl.hpp, line 912
I am unable to debug this error.
Your image angl is not the size or type you think it is, or is empty.
Try checking the type with angl.type() and size with angl.rows angl.cols
If there is a problem it is probably in the phase() call which we don't have, are you sure you are modifying the angl image and not a copy ?
In the worst case, you can debug into OpenCV to check the variables at that assert call which throws the error. To do that, you need to download the source of your OpenCV version and tell the debugger where the source files are located.
Once you have set up the debugging of the OpenCV source, you can simply jump into the .at call with your debugger to see which part of the assert condition fails.
Following is an Assertion Error report (displayed on console) when calling cvtColor() function in opencv giving the argument CV_GRAY2BGR on a Mat object which is already a BGR image. I want to know how to interpret this error message by a person who yet doesn't know what the error here. (Hope some erudites won't vote to close this question as off topic, as I know there is a big value in learning to read Assertion or any other error messages for newbees for c++. ) And as I guess this might be most probably a opencv issue on reading assertion errors.
OpenCV Error: Assertion failed (scn == 1 && (dcn == 3 ||
dcn == 4)) in cv::cvtColor, file C:\builds\2_4_PackSlave-win32-vc12-shared\open
cv\modules\imgproc\src\color.cpp, line 3791
I know 2 conditions are tested here,
(scn == 1)
(dcn == 3 || dcn == 4)
and one of them should have failed which has caused the Assertion error. How to distinct and clarify the failed condition? May be I might have to seek into the cvtColor function source code and that would be no problem. (actually I did it but I couldn't find variables with names scn or dcn there in that improc.cpp class there)
This snippet
#include <opencv2\opencv.hpp>
using namespace cv;
int main(int argc, char** argv)
{
// Just a small green BGR image
Mat3b img(10,10,Vec3b(0,255,0));
Mat1b gray;
cvtColor(img, gray, CV_GRAY2BGR); // WARNING: this won't work (on purpose)
return 0;
}
will produce your exact error:
OpenCV Error: Assertion failed (scn == 1 && (dcn == 3 || dcn == 4)) in cv::cvtCo
lor, file C:\builds\2_4_PackSlave-win32-vc12-static\opencv\modules\imgproc\src\c
olor.cpp, line 3789
This code is obviuosly wrong, because you're trying to convert an BGR image from GRAY.
OpenCV is telling you:
Since you're using the code CV_GRAY2BGR, I'm expecting to convert from GRAY (1 channel) source image to a BGR (3 channel) destination image. (I'll allow also BGRA (4 channels) as destination image, even if CV_GRAY2BGRA would be more appropriate in this case.)
In the documentation OpenCV is telling you:
src: input image: 8-bit unsigned, 16-bit unsigned ( CV_16UC... ), or single-precision floating-point.
dst: output image of the same size and depth as src.
code: color space conversion code (see the description below).
dstCn: number of channels in the destination image; if the parameter is 0, the number of the channels is derived automatically from src and code .
In C++, OpenCV say this as
CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
where scn stands for "Source Channels Number", and dcn stands for "Destination Channels Number".
Now the last point, where do scn and dcn comes from? If you use a debugger and follow the execution path, you'll see in function void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) in color.cpp that (comments added by me):
void cv::cvtColor( InputArray _src /* source image*/,
OutputArray _dst /* destination image*/,
int code, /* here is CV_GRAY2BGR*/
int dcn /* defaults to -1*/ )
{
Mat src = _src.getMat(), dst;
...
int scn = src.channels(); // scn is the number of channels of the source image
...
switch( code ) {
...
case CV_GRAY2BGR: case CV_GRAY2BGRA:
if( dcn <= 0 ) dcn = (code==CV_GRAY2BGRA) ? 4 : 3;
// destination channels are set to 3 because of the code CV_GRAY2BGR
// Check that the input arguments are correct
CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
...
}
calling cvtColor() function in opencv giving the argument CV_GRAY2BGR on a Mat object which is already a BGR image
You have already answered your own question here. The assertion will have originally have been something like:
CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
Since you're using a BGR Mat, scn - which is the number of channels in the source Mat - will be 3 causing the whole expression to evaluate to false, and the assertion to fail.
The operation you are performing makes no sense. Omit it, and your code will probably work.
I am trying to copy one image to another pixel by pixel (I know there are sophisticated methods available. I am trying to solve another problem and answer to this will be useful).
This is my code:
int main()
{
Mat Img;
Img = imread("../../../stereo_images/left01.jpg");
Mat copyImg = Mat::zeros(Img.size(), CV_8U);
for(int i=0; i<Img.rows; i++){
for(int j=0; j<Img.cols; j++){
copyImg.at<uchar>(j,i) = Img.at<uchar>(j,i);
}}
namedWindow("Image", CV_WINDOW_AUTOSIZE );
imshow("Image", Img);
namedWindow("copyImage", CV_WINDOW_AUTOSIZE );
imshow("copyImage", copyImg);
waitKey(0);
return 0;
}
When I run this code in visual studio I get the following error
OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)si
ze.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channel
s()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3
) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file c:\opencv\opencv-2.4.9\ope
ncv\build\include\opencv2\core\mat.hpp, line 537
I know for fact that Img's type is CV_8U. Why does this happen ?
Thanks!
// will read in a rgb image , no matter what the content is
Img = imread("../../../stereo_images/left01.jpg");
to make it read grayscale images use:
Img = imread("../../../stereo_images/left01.jpg", CV_LOAD_IMAGE_GRAYSCALE);
then, you don't need to copy per pixel (and you should even avoid that), just use:
Mat im2 = Img.clone();
if you do per-pixel loops, watch out to get the indices right. it's row-col world here, not x,y, so it should be:
copyImg.at<uchar>(i,j) = Img.at<uchar>(i,j);
in your case
I know for fact that Img's type is CV_8U.
But CV_8U is just the image depth (8-bit U-nsigned). The type also specifies the number of channels, which is usually three. One for blue, one for green and one for red in this order as default for OpenCV. The type would be CV_8UC3 (C-hannels = 3). imread will convert even a black and white image to a 3-channel image by default. imread(filename, CV_LOAD_IMAGE_GRAYSCALE) will load a 1-channel image (CV_8UC1). But if you're not sure the easiest solution is
Mat copyImg = Mat::zeros(Img.size(), Img.type());
To access the array elements you have to know the size of it. Using .at<uchar>() on a 3-channel image will only access the first channel because you have 3*8 bit per pixel. So on a 3-channel image you have to use
copyImg.at<Vec3b>(i,j) = Img.at<Vec3b>(i,j);
where Vec3b is a cv::Vec<uchar, 3>. You should also note that the first argument of at<>(,) is the index along dim 0 which are the rows and second argument cols. Or in other words in classic 2d-xy-chart order you access a pixel with .at<>(y,x) == .at<>(Point(x,y)).
your problem is with this line :
copyImg.at<uchar>(j,i) = Img.at<uchar>(j,i);
It should be :
copyImg.at<uchar>(i,j) = Img.at<uchar>(i,j);
Note that if you want to copy image you can simply do this :
Mat copyImg = Img.clone();
I loaded an Image to a Mat:
Mat Mask = cvLoadImage(filename);
Its an 3744 X 5616 RGB Image. On the next Step i convert it to an Grayscale.
cvtColor(Mask,Mask,CV_BGR2GRAY);
after this i normalize it to use the full Grayscale later:
normalize(Mask,Mask,0,255,NORM_MINMAX,CV_8U);
Now i need the specific Grayscale values and getting an Error on some Values:
for(int i=0;i<(Picture.rows);i++)
{
for(int j=0;j<(Picture.cols);j++)
{
Vec3b masked = Mask.at<Vec3b>(i,j);
//some stuff
}
}
I'm getting the Following Error on some Pixels:
OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && (unsigned)i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3) - 1))*4) & 15) == elemSize1()) in unknown function, file c:\opencv\build\include\opencv2\core\mat.hpp, line 537
Anyone can tell me what i did wrong? It's strange that it appears only on some Pixel Values
Edit:
Additional Information:
If I load my Mask as Grayscale everything works fine. But when I use cvtColor() or Mat Mask = imread(filename,CV_LOAD_IMAGE_GRAYSCALE); on the image the error appears. Very Strange...
I think your problem is you are accessing a binary image with .at<Vec3b>(i,j). Instead you want to access each pixel with .at<uchar>(i,j). cvtColor(Mask,Mask,CV_BGR2GRAY); changes the 3 channel BGR image to a one channel grayscale image. .at<Vec3b>(i,j) is trying to access a 3 channel image which will eventually go past the end of the image array in memory causing problems or tripping those assertions.
The inner part of your for loop should look like this:
unsigned char masked = Mask.at<uchar>(i,j);
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.