Having issues with opencv/dnn with caffe model - opencv

I am trying to make use of openpose example in opencv using caffe model and opencv/dnn.hpp
tutorial I have been following - https://www.learnopencv.com/deep-learning-based-human-pose-estimation-using-opencv-cpp-python/
we require 2 files for the network as said in the tutorial :
1 - prototxt - https://github.com/spmallick/learnopencv/blob/master/OpenPose/pose/coco/pose_deploy_linevec.prototxt
2 - caffe model - posefs1.perception.cs.cmu.edu/OpenPose/models/pose/coco/pose_iter_440000.caffemodel
ros node that I made following the tutorial :
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/dnn/dnn.hpp>
#include <sensor_msgs/image_encodings.h>
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::dnn;
static const std::string OPENCV_WINDOW = "Image window";
#define COCO
#ifdef COCO
const int POSE_PAIRS[17][2] =
{
{1,2}, {1,5}, {2,3},
{3,4}, {5,6}, {6,7},
{1,8}, {8,9}, {9,10},
{1,11}, {11,12}, {12,13},
{1,0},{0,14},
{14,16}, {0,15}, {15,17}
};
static const std::string protoFile = "pose/coco/pose_deploy_linevec.prototxt";
static const std::string weightsFile = "pose/coco/pose_iter_440000.caffemodel";
int nPoints = 18;
#endif
class ImageConverter
{
ros::NodeHandle nh_;
image_transport::ImageTransport it_;
image_transport::Subscriber image_sub_;
public:
ImageConverter()
: it_(nh_)
{
image_sub_ = it_.subscribe("/zed/rgb/image_raw_color", 1, &ImageConverter::imageCb, this);
}
~ImageConverter()
{
cv::destroyWindow(OPENCV_WINDOW);
}
void imageCb(const sensor_msgs::ImageConstPtr& msg)
{
cv_bridge::CvImagePtr cv_ptr;
try
{
cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
}
catch (cv_bridge::Exception& e)
{
ROS_ERROR("cv_bridge exception: %s", e.what());
return;
}
if (cv_ptr->image.rows > 60 && cv_ptr->image.cols > 60)
detect_people(cv_ptr->image);
cv::waitKey(3);
}
void detect_people(cv::Mat msg)
{
int inWidth = msg.cols;
int inHeight = msg.rows;
float thresh = 0.1;
cv::Mat frame;
msg.copyTo(frame);
cv::Mat frameCopy = frame.clone();
int frameWidth = frame.cols;
int frameHeight = frame.rows;
cv::dnn::Net net = cv::dnn::readNetFromCaffe("pose_deploy_linevec.prototxt" ,"pose_iter_440000.caffemodel");
cv::Mat inpBlob = blobFromImage(frame, 1.0/255, cv::Size(inWidth, inHeight), cv::Scalar(0, 0, 0), false, false);
net.setInput(inpBlob);
cv::Mat output = net.forward();
int H = output.size[2];
int W = output.size[3];
std::vector<cv::Point> points(nPoints);
for (int n=0; n < nPoints; n++)
{
// Probability map of corresponding body's part.
cv::Mat probMap(H, W, CV_32F, output.ptr(0,n));
cv::Point2f p(-1,-1);
cv::Point maxLoc;
double prob;
cv::minMaxLoc(probMap, 0, &prob, 0, &maxLoc);
if (prob > thresh)
{
p = maxLoc;
p.x *= (float)frameWidth / W ;
p.y *= (float)frameHeight / H ;
cv::circle(frameCopy, cv::Point((int)p.x, (int)p.y), 8, Scalar(0,255,255), -1);
cv::putText(frameCopy, cv::format("%d", n), cv::Point((int)p.x, (int)p.y), cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(0, 0, 255), 2);
}
points[n] = p;
}
int nPairs = sizeof(POSE_PAIRS)/sizeof(POSE_PAIRS[0]);
for (int n = 0; n < nPairs; n++)
{
// lookup 2 connected body/hand parts
Point2f partA = points[POSE_PAIRS[n][0]];
Point2f partB = points[POSE_PAIRS[n][1]];
if (partA.x<=0 || partA.y<=0 || partB.x<=0 || partB.y<=0)
continue;
cv::line(frame, partA, partB, cv::Scalar(0,255,255), 8);
cv::circle(frame, partA, 8, cv::Scalar(0,0,255), -1);
cv::circle(frame, partB, 8, cv::Scalar(0,0,255), -1);
}
cv::imshow("Output-Skeleton", frame);
}
};
int main(int argc, char** argv)
{
ros::init(argc, argv, "image_converter");
ros::NodeHandle nh_;
ros::Publisher pub;
ImageConverter ic;
ros::spin();
return 0;
}
The code is compiled without any errors, but while I run the code it gives the following error msg :
I get the following error when I run the node
error - OpenCV Error: Unspecified error (FAILED: fs.is_open(). Can't open "pose_deploy_linevec.prototxt") in ReadProtoFromTextFile, file /tmp/binarydeb/ros-kinetic-opencv3-3.3.1/modules/dnn/src/caffe/caffe_io.cpp, line 1119
terminate called after throwing an instance of 'cv::Exception'
what(): /tmp/binarydeb/ros-kinetic-opencv3-3.3.1/modules/dnn/src/caffe/caffe_io.cpp:1119: error: (-2) FAILED: fs.is_open(). Can't open "pose_deploy_linevec.prototxt" in function ReadProtoFromTextFile
Aborted (core dumped)
please help me solve this issue.

This issue is probably with the windows users only.
Solve the issue by:
Using/Adding absolute path when calling prototxt file.
Add the extension too. For Example:
"pose/coco/pose_deploy_linevec.prototxt.txt"
Spent 3 hours debugging this myself. Hope it helped someone else.

You are selecting the wrong file path.
Just replace this line:
static const std::string protoFile = "pose/coco/pose_deploy_linevec.prototxt";
with the path of the prototxt file in your laptop like this:
static const std::string protoFile = "C:/Users/lenovo/Desktop/learnopencv-master/OpenPose/pose/coco/pose_deploy_linevec.prototxt";

Related

Why is webcam image processing slow while using Xcode in an OpenCV project?

Why is webcam image processing is very slow while using Xcode for this OpenCV project, and only one out of three windows are working (similar spaces and HSV windows are not turning up) and are very slow? How to increase the speed of execution of the program?
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat img, hsv, res;
char *win1 = "RGB";
char *win2 = "HSV";
char *win3 = "similar spaces";
uchar thresh = 5;
void setColor(uchar hval){
int i,j;
for (i = 0; i < res.rows; ++i){
for (j = 0; j < res.cols; ++j){
if( hsv.at<Vec3b>(i,j)[0] <= hval+thresh
&& hsv.at<Vec3b>(i,j)[0] >= hval-thresh)
res.at<uchar>(i,j) = 255;
else res.at<uchar>(i,j) = 0;
}
}
imshow(win3, res);
}
void MouseCallBackFunc(int event, int x, int y, int flags, void* userdata){
if(event==EVENT_LBUTTONDOWN){
cout<<"\t x,y : "<<x<<','<<y<<endl;
cout<<'\t'<<img.at<Vec3b>(y,x)<<endl;
setColor(hsv.at<Vec3b>(y,x)[0]);
}
}
int main()
{
img = imread("/usr/share/opencv/samples/cpp/stuff.jpg", CV_LOAD_IMAGE_COLOR);
hsv = Mat::zeros(img.size(), CV_8UC3);
res = Mat::zeros(img.size(), CV_8UC1);
char c;
int i,j;
namedWindow(win2, CV_WINDOW_NORMAL);
namedWindow(win3, CV_WINDOW_NORMAL);
cvtColor(img, hsv, CV_RGB2HSV);
imshow(win1, img);
imshow(win2, hsv);
imshow(win3, res);
setMouseCallback(win1, MouseCallBackFunc, NULL);
// VideoCapture stream(0); //0 is the id of video device.0 if you have only one camera.
// if (!stream.isOpened()) { //check if video device has been initialised
// cout << "cannot open camera";
// }
// while (true) {
// Mat cameraFrame;
// stream.read(cameraFrame);
// imshow("test", cameraFrame);
// c = waitKey(30);
// if(c==27)
// break;
// }
while((c=waitKey(300))!=27){}
return 0;
}

Extracting Hough lines intersection coordinate and getting the data to Notepad or Excel

I need help to get the coordinates of the lines that HoughLines produced and extract it to an output file (Notepad, Excel, or any other output files).
I managed to obtain the lines and based on my research on this site I found a post that tells how to obtain the coordinates, however due to my limited understanding I could not get the code to run along my original Hough code and get the intersection points coordinate onto an output file.
Here is my original Hough code:
#pragma once
#include <C:\OpenCV2.2\include\opencv\cv.h>
#include <C:\OpenCV2.2\include\opencv\highgui.h>
#include <C:\OpenCV2.2\include\opencv2\core\core.hpp>
#include <C:\OpenCV2.2\include\opencv2\imgproc\imgproc.hpp>
#include <C:\OpenCV2.2\include\opencv2\highgui\highgui.hpp>
#include <stdio.h>
#include <math.h>
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
cv::Mat dst_img, gray_img, contour_img, contrast_img;
cv::Mat src_img = cv::imread("C:\\Frame-1.bmp"); //Source image path
dst_img = src_img.clone();
dst_img.convertTo(contrast_img, -1, 1.5, 0);
cv::cvtColor(contrast_img, gray_img, CV_BGR2GRAY);
cv::Canny(gray_img, contour_img, 75, 225, 3);
vector<Vec2f> lines_;
HoughLines(contour_img, lines_, 1, CV_PI/180, 200);
for( size_t i = 0; i < lines_.size(); i++ )
{
float rho = lines_[i][0];
float theta = lines_[i][1];
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
Point pt1(cvRound(x0 + 1000*(-b)),
cvRound(y0 + 1000*(a)));
Point pt2(cvRound(x0 - 1000*(-b)),
cvRound(y0 - 1000*(a)));
cv::clipLine(gray_img.size(), pt1, pt2);
if(!dst_img.empty())
line( dst_img, pt1, pt2, Scalar(0, 0, 255), 1, CV_AA);
cv::imwrite("result.bmp", dst_img);
}
namedWindow("My Image");
imshow("My Image", dst_img);
waitKey(0);
return 0;
}
And here is the link to the code that I wanted to put into my original code:
I am struck at finding the point of intersection of most lines in an image
Right now my original code draws Houghlines and exports the image (as result.bmp) and at the same time displays the image on a new window.
I just need to figure how and where to put the new code plus an additional code to obtain the raw data of the coordinates onto an output file like Notepad, most desirably in the same folder as result.bmp (the name of the output file could be anything, just needed it to be there).
Sorry if this question sounds like a beginner`s question (I really am) and any help is much appreciated. Many thanks in advance.
Additional information: I am using OpenCV 2.2 and Microsoft Visual Studio Academic 2010
EDIT: This is all three codes (Hough, Coordinate extraction, and Exporting data to notepad) but as a complete beginner I don`t know to make them all work in a single code.
#pragma once
#include <C:\OpenCV2.2\include\opencv\cv.h>
#include <C:\OpenCV2.2\include\opencv\highgui.h>
#include <C:\OpenCV2.2\include\opencv2\core\core.hpp>
#include <C:\OpenCV2.2\include\opencv2\imgproc\imgproc.hpp>
#include <C:\OpenCV2.2\include\opencv2\highgui\highgui.hpp>
#include <stdio.h>
#include <math.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#define PointMinusPoint(P,Q,R) {(P).x = (Q).x - (R).x; (P).y = (Q).y - (R).y;}
#define PointCross(P,Q) (((P).x*(Q).y)-((P).y*(Q).x))
#define SIGN(X) (((X)>=0)? 1:-1 )
#define ABS(a) ((a) >= 0 ? (a) : (-(a)))
#define ROUND(a) ((SIGN(a)) * ( ( int )( ABS(a) + 0.5 ) ) )
typedef struct{
int x,y;
} MYintPOINT;
typedef struct {
MYintPOINT pStart;
MYintPOINT pEnd;
} MyLine;
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
cv::Mat dst_img, gray_img, contour_img, contrast_img;
cv::Mat src_img = cv::imread("C:\\Frame-1.bmp"); //Source image path
dst_img = src_img.clone();
dst_img.convertTo(contrast_img, -1, 1.5, 0);
cv::cvtColor(contrast_img, gray_img, CV_BGR2GRAY);
cv::Canny(gray_img, contour_img, 75, 225, 3);
vector<Vec2f> lines_;
HoughLines(contour_img, lines_, 1, CV_PI/180, 200);
for( size_t i = 0; i < lines_.size(); i++ )
{
float rho = lines_[i][0];
float theta = lines_[i][1];
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
Point pt1(cvRound(x0 + 1000*(-b)),
cvRound(y0 + 1000*(a)));
Point pt2(cvRound(x0 - 1000*(-b)),
cvRound(y0 - 1000*(a)));
cv::clipLine(gray_img.size(), pt1, pt2);
if(!dst_img.empty())
line( dst_img, pt1, pt2, Scalar(0, 0, 255), 1, CV_AA);
cv::imwrite("result.bmp", dst_img);
}
int findLinesIntersectionPoint(const MyLine*l1, const MyLine*l2, MYintPOINT *res){
MYintPOINT p = l1->pStart;
MYintPOINT dp;
MYintPOINT q = l2->pStart;
MYintPOINT dq;
MYintPOINT qmp; // q-p
int dpdq_cross; // 2 cross products
int qpdq_cross; // dp with dq, q-p with dq
float a;
PointMinusPoint(dp,l1->pEnd,l1->pStart);
PointMinusPoint(dq,l2->pEnd,l2->pStart);
PointMinusPoint(qmp,q,p);
dpdq_cross = PointCross(dp,dq);
if (!dpdq_cross){
// Perpendicular Lines
return 0;
}
qpdq_cross = PointCross(qmp,dq);
a = (qpdq_cross*1.0f/dpdq_cross);
res->x = ROUND(p.x+a*dp.x);
res->y = ROUND(p.y+a*dp.y);
return 1;
}
string FileName= FileName_S.c_str();
string::size_type Extension = FileName_S.find_last_of('.'); // Find extension point
Mat mInputImg;
mInputImg= imread(FileName_S,1);
Size szInput= mInputImg.size();
const string DestinationFileName = FileName_S.substr(0, Extension) + "_ImageData.csv"; // Form the new name with container
ofstream myfile (DestinationFileName.c_str());
if (!myfile.is_open())
{
MessageBox(L"Unable to Open File");
}
string Text= format("Row, Col , Pixel Data,\n");
myfile << Text;
for (int Row = 0; Row < szInput.height; Row++)
{
for (int Col = 0; Col < szInput.width; Col++)
{
string Text= format("%d , %d , %d",Row,Col,mInputImg.at<uchar>(Row,Col));
myfile << Text;
myfile << "\n";
}
}
myfile.close();
namedWindow("My Image");
imshow("My Image", dst_img);
waitKey(0);
return 0;
}
It is very easy to export your data to Notepad or excel file. Here is the code to Export a mat to a csv File. Format your String with your desired data to export your desired data.
/*Exporting a Mat to Excel(.csv) file*/
string FileName= FileName_S.c_str();
string::size_type Extension = FileName_S.find_last_of('.'); // Find extension point
Mat mInputImg;
mInputImg= imread(FileName_S,1);
Size szInput= mInputImg.size();
const string DestinationFileName = FileName_S.substr(0, Extension) + "_ImageData.csv"; // Form the new name with container
ofstream myfile (DestinationFileName.c_str());
if (!myfile.is_open())
{
MessageBox(L"Unable to Open File");
}
string Text= format("Row, Col , Pixel Data,\n");
myfile << Text;
for (int Row = 0; Row < szInput.height; Row++)
{
for (int Col = 0; Col < szInput.width; Col++)
{
string Text= format("%d , %d , %d",Row,Col,mInputImg.at<uchar>(Row,Col));
myfile << Text;
myfile << "\n";
}
}
myfile.close();

Cannot add 4 numbers to mat opencv

I created a mat object in opencv , dimension Nx4 , in which I want to put N coordinates.
[Px Py 1 0]
[Py Px 0 1]
For this I wrote the following code :
vector<Point2f> features1 , features2;
Mat features_1;
for(int i = 0 , j = 0; i < feature1.size() ; ++i , j+=2)
{
features_1.at<Vec3d>(j) = {feature1[i].x , feature1[i].y , 1 , 0};
features_1.at<Vec3d>(j) = {feature1[i].y , -feature1[i].x , 0 , 1};
}
But at the first line of the loop I get the following error :
cv::Matx<_Tp, m, n>::Matx(_Tp, _Tp, _Tp, _Tp) [with _Tp = double; int m = 3; int n = 1]: Assertion channels >= 4' failed.
How can I solve this?
it's probably easier to push_back() single elements to a Mat, and later do a reshape().
this will make a 2*N x 4 Mat:
vector<Point2f> features1 , features2;
Mat features_1;
for(size_t i=0; i<feature1.size() ; ++i)
{
features_1.push_pack(feature1[i].x);
features_1.push_pack(feature1[i].y);
features_1.push_pack(1);
features_1.push_pack(0);
features_1.push_pack(feature2[i].y);
features_1.push_pack(feature2[i].x);
features_1.push_pack(0);
features_1.push_pack(1);
}
features_1 = features_1.reshape(1,4); // or reshape(1,features1.size()*2); //for 4xN*2
Where you wrote <Vec3d>, did you mean <Vec4d>?
Your code is not close to correct, but here is a minimal example of how your desired result can be achieved (if you don't have C++11, just use an old style iterator in the loop)
#include <iostream>
#include <vector>
using namespace std;
#include <opencv2/core/core.hpp>
using namespace cv;
int main()
{
vector<Point2f> feature1;
feature1.push_back(Point2f(1.0f, 2.0f));
feature1.push_back(Point2f(3.0f, 4.0f));
Mat features_1;
for(auto p : feature1)
{
features_1.push_back(Vec4d(p.x, p.y , 1 , 0));
features_1.push_back(Vec4d(p.y, -p.x , 0, 1));
}
// At this point the mat is (N, 1, CV_64FC4)
// Reshape if you want (N, 4, CV_64FC1);
features_1 = features_1.reshape(1,4);
cout << features_1;
}
This output of this is:
[1, 2, 1, 0;
2, -1, 0, 1;
3, 4, 1, 0;
4, -3, 0, 1]
However, if the features_1 is already allocated and you can't just use push_back, apart from releasing the mat, you could do this (assuming features_1.isContinuous() is true):
#include <iostream>
#include <vector>
using namespace std;
#include <opencv2/core/core.hpp>
using namespace cv;
int main()
{
vector<Point2f> feature1;
feature1.push_back(Point2f(1.0f, 2.0f));
feature1.push_back(Point2f(3.0f, 4.0f));
Mat features_1(2 * feature1.size(), 4, CV_64FC1);
Vec4d* ptr = features_1.ptr<Vec4d>(0);
for(auto p : feature1)
{
*ptr++ = Vec4d(p.x, p.y , 1 , 0);
*ptr++ = Vec4d(p.y, -p.x , 0, 1);
}
cout << features_1 << endl;
}
The above produces the same result as the previous version.
If there is any possibility in the above example that features_1.isContinuous() is false, you can use an iterator to scan features_1:
auto ptr = features_1.begin<double>();
for(auto p : feature1)
{
*ptr++ = p.x;
*ptr++ = p.y;
*ptr++ = 1;
*ptr++ = 0;
*ptr++ = p.y;
*ptr++ = -p.x;
*ptr++ = 0;
*ptr++ = 1;
}

Image Processing Opencv

I am having doubt in opencv. I'm trying to implement SURF algorithm. When I trying to build the code but I'm getting the following error.
*****error LNK2019: unresolved external symbol _cvExtractSURF referenced in function _main
1>SAMPLE.obj : error LNK2019: unresolved external symbol _cvSURFParams referenced in function _main*****
I have gone through all the posts related to my topic in this forum, but couldn't figure out the problem with my code. Please help me in resolving my problem.
code :
#include <stdio.h>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2\objdetect\objdetect.hpp>
#include <opencv2\calib3d\calib3d.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\legacy\legacy.hpp>
#include <opencv2\legacy\compat.hpp>
#include <opencv2/nonfree/nonfree.hpp>
#include <opencv\opensurf\surf.h>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
CvMemStorage* storage = cvCreateMemStorage(0);
cvNamedWindow("Image", 1);
int key = 0;
static CvScalar red_color[] ={0,0,255};
IplImage* capture= cvLoadImage( "testface.jpg");
CvMat* prevgray = 0, *image = 0, *gray =0;
while( key != 'q' )
{
int firstFrame = gray == 0;
IplImage* frame =capture;
if(!frame)
break;
if(!gray)
{
image = cvCreateMat(frame->height, frame->width, CV_8UC1);
}
//Convert the RGB image obtained from camera into Grayscale
cvCvtColor(frame, image, CV_BGR2GRAY);
//Define sequence for storing surf keypoints and descriptors
CvSeq *imageKeypoints = 0, *imageDescriptors = 0;
int i;
//Extract SURF points by initializing parameters
CvSURFParams params = cvSURFParams(500,1);
cvExtractSURF( image, 0, &imageKeypoints, &imageDescriptors, storage, params );
printf("Image Descriptors: %d\n", imageDescriptors->total);
//draw the keypoints on the captured frame
for( i = 0; i < imageKeypoints->total; i++ )
{
CvSURFPoint* r = (CvSURFPoint*)cvGetSeqElem( imageKeypoints, i );
CvPoint center;
int radius;
center.x = cvRound(r->pt.x);
center.y = cvRound(r->pt.y);
radius = cvRound(r->size*1.2/9.*2);
cvCircle( frame, center, radius, red_color[0], 1, 8, 0 );
}
cvShowImage( "Image", frame );
cvWaitKey(0);
}
cvDestroyWindow("Image");
return 0
}
Thank you,
Sreelakshmi Priya

Can you improve this solution to interfacing OpenCV 2.4+ to Zxing 1D barcode reader

I didn't find this solution on the net, had to figure it myself. So, for benefit of others, I'm posing this as a "question":
Can you improve my working interface of OpenCV 2.4+ to the C++ version of Zxing 2.2 1D barcode reader?
Here's my working but perhaps improvable implementation below:
/**
* Gary Bradski, Reading 1D barcodes
* License BSD, (c) 2013
*
* Working example of how to call zxing using OpenCV 2.4+ cv::Mat
*
* Calling example, this one for 128 barcodes:
*
* Code128Reader cr; //Instantiate a zxing barcode reader, int this case for 128 barcodes,
* // but you can use any of their 1D or multi readers here
* ... by magic, I find, rectify and islotate a barcode into cv::Mat barcodeImage
* decode_image(&cr, barcodeImage); //Decode the isolated rectified barcode or fail
*
*/
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
//////////////ZXING BARCODE READER//////////////////////////////////////////
#include <zxing/LuminanceSource.h>
#include <zxing/MultiFormatReader.h>
#include <zxing/oned/OneDReader.h>
#include <zxing/oned/EAN8Reader.h>
#include <zxing/oned/EAN13Reader.h>
#include <zxing/oned/Code128Reader.h>
#include <zxing/datamatrix/DataMatrixReader.h>
#include <zxing/qrcode/QRCodeReader.h>
#include <zxing/aztec/AztecReader.h>
#include <zxing/common/GlobalHistogramBinarizer.h>
#include <zxing/Exception.h>
using namespace zxing;
using namespace oned;
using namespace datamatrix;
using namespace qrcode;
using namespace aztec;
class OpenCVBitmapSource : public LuminanceSource
{
private:
cv::Mat m_pImage;
public:
OpenCVBitmapSource(cv::Mat &image)
: LuminanceSource(image.cols, image.rows)
{
m_pImage = image.clone();
}
~OpenCVBitmapSource(){}
int getWidth() const { return m_pImage.cols; }
int getHeight() const { return m_pImage.rows; }
ArrayRef<char> getRow(int y, ArrayRef<char> row) const //See Zxing Array.h for ArrayRef def
{
int width_ = getWidth();
if (!row)
row = ArrayRef<char>(width_);
const char *p = m_pImage.ptr<char>(y);
for(int x = 0; x<width_; ++x, ++p)
row[x] = *p;
return row;
}
ArrayRef<char> getMatrix() const
{
int width_ = getWidth();
int height_ = getHeight();
ArrayRef<char> matrix = ArrayRef<char>(width_*height_);
for (int y = 0; y < height_; ++y)
{
const char *p = m_pImage.ptr<char>(y);
int yoffset = y*width_;
for(int x = 0; x < width_; ++x, ++p)
{
matrix[yoffset + x] = *p;
}
}
return matrix;
}
/*
// The following methods are not supported by this demo (the DataMatrix Reader doesn't call these methods)
bool isCropSupported() const { return false; }
Ref<LuminanceSource> crop(int left, int top, int width, int height) {}
bool isRotateSupported() const { return false; }
Ref<LuminanceSource> rotateCounterClockwise() {}
*/
};
void decode_image(Reader *reader, cv::Mat &image)
{
try
{
Ref<OpenCVBitmapSource> source(new OpenCVBitmapSource(image));
Ref<Binarizer> binarizer(new GlobalHistogramBinarizer(source));
Ref<BinaryBitmap> bitmap(new BinaryBitmap(binarizer));
Ref<Result> result(reader->decode(bitmap, DecodeHints(DecodeHints::TRYHARDER_HINT)));//+DecodeHints::DEFAULT_HINT)));
cout << result->getText()->getText() << endl;
//Export the read barcode here
}
catch (zxing::Exception& e)
{
//Export your failure to read the code here
cerr << "Error: " << e.what() << endl;
}
}
Forgot to attribute what I started with. There is an out of date (will not compile) implementation using IplImages here:
http://www.idealsoftware.com/opensource/scan-1d-2d-barcodes-webcam-zxing-opencv-visual-c.html
This updates that solution so that it works with Zxing 2.2 and OpenCV 2.1+
I think you can avoid the matrix copy by replacing
Ref<OpenCVBitmapSource> source(new OpenCVBitmapSource(image));
With
Ref<LuminanceSource> source(new GreyscaleLuminanceSource(image.data, image.step, image.rows, 0, 0, image.cols, image.rows));

Resources