Skip to content

Commit

Permalink
Merge pull request #41 from geduino-foundation/master
Browse files Browse the repository at this point in the history
OpenCV MatSource
  • Loading branch information
aidansteele authored Nov 22, 2016
2 parents 49a82bb + 67ad485 commit 749925a
Show file tree
Hide file tree
Showing 5 changed files with 403 additions and 0 deletions.
25 changes: 25 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,23 @@ if(WIN32)
set(LIBZXING_FILES ${LIBZXING_FILES} ${LIBZXING_WIN32_FILES})
include_directories(SYSTEM "./core/lib/win32/")
endif()

# OpenCV classes
find_package(OpenCV)
if(OpenCV_FOUND)
file(GLOB_RECURSE LIBZXING_OPENCV_FILES
"./opencv/src/*.cpp"
"./opencv/src/*.h"
)
set(LIBZXING_FILES ${LIBZXING_FILES} ${LIBZXING_OPENCV_FILES})
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories("./opencv/src/")
endif()

include_directories("./core/src/")
add_library(libzxing ${LIBZXING_FILES})
set_target_properties(libzxing PROPERTIES PREFIX "")

find_package(Iconv)
if(ICONV_FOUND)
include_directories(${ICONV_INCLUDE_DIR})
Expand All @@ -61,11 +75,22 @@ else()
add_definitions(-DNO_ICONV=1)
endif()

# Add OpenCV cli executable
if(OpenCV_FOUND)
file(GLOB_RECURSE OPENCV_ZXING_FILES
"./opencv-cli/src/*.cpp"
"./opencv-cli/src/*.h"
)
add_executable(zxing-cv ${OPENCV_ZXING_FILES})
target_link_libraries(zxing-cv libzxing ${OpenCV_LIBRARIES})
endif()

# Add cli executable.
file(GLOB_RECURSE ZXING_FILES
"./cli/src/*.cpp"
"./cli/src/*.h"
)

add_executable(zxing ${ZXING_FILES})
target_link_libraries(zxing libzxing)
install(TARGETS zxing libzxing
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ You can switch between build modes by specifying:
- `-DCMAKE_BUILD_TYPE=Debug` or
- `-DCMAKE_BUILD_TYPE=Release`

# OpenCV integration

When build on a system where opencv is installed the open cv bridge classes and executable will be built too.

# Development tips

To profile the code (very useful to optimize the code):
Expand Down
254 changes: 254 additions & 0 deletions opencv-cli/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
/*
* Copyright 2010-2011 Alessandro Francescon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <string>
#include <exception>
#include <stdlib.h>
#include <zxing/common/Counted.h>
#include <zxing/Binarizer.h>
#include <zxing/MultiFormatReader.h>
#include <zxing/Result.h>
#include <zxing/ReaderException.h>
#include <zxing/common/GlobalHistogramBinarizer.h>
#include <zxing/Exception.h>
#include <zxing/common/IllegalArgumentException.h>
#include <zxing/BinaryBitmap.h>
#include <zxing/DecodeHints.h>
#include <zxing/qrcode/QRCodeReader.h>
#include <zxing/MultiFormatReader.h>
#include <zxing/MatSource.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace zxing;
using namespace zxing::qrcode;
using namespace cv;

void printUsage(char** argv) {

// Print usage
cout << "Usage: " << argv[0] << " [-d <DEVICE>] [-w <CAPTUREWIDTH>] [-h <CAPTUREHEIGHT>]" << endl
<< "Read QR code from given video device." << endl
<< endl;

}

Point toCvPoint(Ref<ResultPoint> resultPoint) {
return Point(resultPoint->getX(), resultPoint->getY());
}

int main(int argc, char** argv) {

int deviceId = 0;
int captureWidth = 640;
int captureHeight = 480;
bool multi = false;

for (int j = 0; j < argc; j++) {

// Get arg
string arg = argv[j];

if (arg.compare("-d") == 0) {

if ((j + 1) < argc) {

// Set device id
deviceId = atoi(argv[++j]);

} else {

// Log
cerr << "Missing device id after -d" << endl;
printUsage(argv);
return 1;

}

} else if (arg.compare("-w") == 0) {

if ((j + 1) < argc) {

// Set capture width
captureWidth = atoi(argv[++j]);

} else {

// Log
cerr << "Missing width after -w" << endl;
printUsage(argv);
return 1;

}

} else if (arg.compare("-h") == 0) {

if ((j + 1) < argc) {

// Set capture height
captureHeight = atoi(argv[++j]);

} else {

// Log
cerr << "Missing height after -h" << endl;
printUsage(argv);
return 1;

}

} else if (arg.compare("-m") == 0) {

// Set multi to true
multi = true;

}

}

// Log
cout << "Capturing from device " << deviceId << "..." << endl;

// Open video captire
VideoCapture videoCapture(deviceId);

if (!videoCapture.isOpened()) {

// Log
cerr << "Open video capture failed on device id: " << deviceId << endl;
return -1;

}

if (!videoCapture.set(CV_CAP_PROP_FRAME_WIDTH, captureWidth)) {

// Log
cerr << "Failed to set frame width: " << captureWidth << " (ignoring)" << endl;

}

if (!videoCapture.set(CV_CAP_PROP_FRAME_HEIGHT, captureHeight)) {

// Log
cerr << "Failed to set frame height: " << captureHeight << " (ignoring)" << endl;

}

// The captured image and its grey conversion
Mat image, grey;

// Open output window
namedWindow("ZXing", cv::WINDOW_AUTOSIZE);

// Stopped flag will be set to -1 from subsequent wayKey() if no key was pressed
int stopped = -1;

while (stopped == -1) {

// Capture image
bool result = videoCapture.read(image);

if (result) {

// Convert to grayscale
cvtColor(image, grey, CV_BGR2GRAY);

try {

// Create luminance source
Ref<LuminanceSource> source = MatSource::create(grey);

// Search for QR code
Ref<Reader> reader;

if (multi) {
reader.reset(new MultiFormatReader);
} else {
reader.reset(new QRCodeReader);
}

Ref<Binarizer> binarizer(new GlobalHistogramBinarizer(source));
Ref<BinaryBitmap> bitmap(new BinaryBitmap(binarizer));
Ref<Result> result(reader->decode(bitmap, DecodeHints(DecodeHints::TRYHARDER_HINT)));

// Get result point count
int resultPointCount = result->getResultPoints()->size();

for (int j = 0; j < resultPointCount; j++) {

// Draw circle
circle(image, toCvPoint(result->getResultPoints()[j]), 10, Scalar( 110, 220, 0 ), 2);

}

// Draw boundary on image
if (resultPointCount > 1) {

for (int j = 0; j < resultPointCount; j++) {

// Get start result point
Ref<ResultPoint> previousResultPoint = (j > 0) ? result->getResultPoints()[j - 1] : result->getResultPoints()[resultPointCount - 1];

// Draw line
line(image, toCvPoint(previousResultPoint), toCvPoint(result->getResultPoints()[j]), Scalar( 110, 220, 0 ), 2, 8 );

// Update previous point
previousResultPoint = result->getResultPoints()[j];

}

}

if (resultPointCount > 0) {

// Draw text
putText(image, result->getText()->getText(), toCvPoint(result->getResultPoints()[0]), FONT_HERSHEY_PLAIN, 1, Scalar( 110, 220, 0 ));

}

} catch (const ReaderException& e) {
cerr << e.what() << " (ignoring)" << endl;
} catch (const zxing::IllegalArgumentException& e) {
cerr << e.what() << " (ignoring)" << endl;
} catch (const zxing::Exception& e) {
cerr << e.what() << " (ignoring)" << endl;
} catch (const std::exception& e) {
cerr << e.what() << " (ignoring)" << endl;
}

// Show captured image
imshow("ZXing", image);

// Wait a key for 1 millis
stopped = waitKey(1);

} else {

// Log
cerr << "video capture failed" << endl;

}

}

// Release video capture
videoCapture.release();

return 0;

}
82 changes: 82 additions & 0 deletions opencv/src/zxing/MatSource.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2010-2011 Alessandro Francescon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "MatSource.h"
#include <zxing/common/IllegalArgumentException.h>

zxing::Ref<zxing::LuminanceSource> MatSource::create(cv::Mat & cvImage) {
return zxing::Ref<LuminanceSource>(new MatSource(cvImage));
}

MatSource::MatSource(cv::Mat & _cvImage) : zxing::LuminanceSource(_cvImage.cols, _cvImage.rows) {
cvImage = _cvImage.clone();
}

zxing::ArrayRef<char> MatSource::getRow(int y, zxing::ArrayRef<char> row) const {

// Get width
int width = getWidth();

if (!row) {

// Create row
row = zxing::ArrayRef<char>(width);

}

// Get pointer to row
const char *p = cvImage.ptr<char>(y);

for(int x = 0; x < width; ++x, ++p) {

// Set row at index x
row[x] = *p;

}

return row;

}

zxing::ArrayRef<char> MatSource::getMatrix() const {

// Get width and height
int width = getWidth();
int height = getHeight();

// Create matrix
zxing::ArrayRef<char> matrix = zxing::ArrayRef<char>(width * height);

for (int y = 0; y < height; ++y) {

// Get pointer to row
const char *p = cvImage.ptr<char>(y);

// Calculate y offset
int yoffset = y * width;

for(int x = 0; x < width; ++x, ++p) {

// Set row at index x with y offset
matrix[yoffset + x] = *p;

}

}

return matrix;

}
Loading

0 comments on commit 749925a

Please sign in to comment.