summaryrefslogtreecommitdiff
path: root/mv_barcode
diff options
context:
space:
mode:
authorTae-Young Chung <ty83.chung@samsung.com>2021-04-19 17:21:56 +0900
committerTae-Young Chung <ty83.chung@samsung.com>2021-05-04 09:17:32 +0000
commit954aabf92059bde43253a47937e2d876a5e6b426 (patch)
tree5f2ce0b520b254707fbd3c51e8dba4360d7337b5 /mv_barcode
parent76596b737533d09d90ca97ba6a7d9cca9ef97f0b (diff)
downloadmediavision-954aabf92059bde43253a47937e2d876a5e6b426.tar.gz
mediavision-954aabf92059bde43253a47937e2d876a5e6b426.tar.bz2
mediavision-954aabf92059bde43253a47937e2d876a5e6b426.zip
Add rotation functionality and CLAHE preprocessing in Barcode modulesubmit/tizen/20210506.010918
Change-Id: I806ad1e20a2b3a436b14b26d41218dbfa3c7fe32 Signed-off-by: Tae-Young Chung <ty83.chung@samsung.com> (cherry picked from commit a9bcad59c6c72b617a836e0e4687f0a9ef52a7e6)
Diffstat (limited to 'mv_barcode')
-rw-r--r--mv_barcode/barcode_detector/CMakeLists.txt10
-rw-r--r--mv_barcode/barcode_detector/include/BarcodeUtils.h13
-rw-r--r--mv_barcode/barcode_detector/src/BarcodeUtils.cpp100
-rw-r--r--mv_barcode/barcode_detector/src/mv_barcode_detect_open.cpp218
4 files changed, 275 insertions, 66 deletions
diff --git a/mv_barcode/barcode_detector/CMakeLists.txt b/mv_barcode/barcode_detector/CMakeLists.txt
index 8ff46123..123d3fbe 100644
--- a/mv_barcode/barcode_detector/CMakeLists.txt
+++ b/mv_barcode/barcode_detector/CMakeLists.txt
@@ -15,12 +15,20 @@ file(GLOB MV_BARCODE_DET_INC_LIST "${PROJECT_SOURCE_DIR}/include/*.h")
file(GLOB MV_BARCODE_DET_SRC_LIST "${PROJECT_SOURCE_DIR}/src/*.cpp"
"${PROJECT_SOURCE_DIR}/src/*.c")
+find_package(OpenCV REQUIRED core imgproc)
+if(NOT OpenCV_FOUND)
+ message(SEND_ERROR "Failed to find OpenCV")
+ return()
+else()
+ include_directories(${OpenCV_INCLUDE_DIRS})
+endif()
+
if(FORCED_STATIC_BUILD)
add_library(${PROJECT_NAME} STATIC ${MV_BARCODE_DET_INC_LIST} ${MV_BARCODE_DET_SRC_LIST})
else()
add_library(${PROJECT_NAME} SHARED ${MV_BARCODE_DET_INC_LIST} ${MV_BARCODE_DET_SRC_LIST})
endif()
-target_link_libraries(${PROJECT_NAME} ${MV_COMMON_LIB_NAME} zbar dlog)
+target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} ${MV_COMMON_LIB_NAME} zbar dlog)
INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR})
diff --git a/mv_barcode/barcode_detector/include/BarcodeUtils.h b/mv_barcode/barcode_detector/include/BarcodeUtils.h
index 58f30c61..4b06ae53 100644
--- a/mv_barcode/barcode_detector/include/BarcodeUtils.h
+++ b/mv_barcode/barcode_detector/include/BarcodeUtils.h
@@ -18,6 +18,8 @@
#define __MEDIA_VISION_BARCODE_UTILS_H__
#include "mv_common.h"
+#include <opencv2/core/core.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
namespace zbar {
class Image;
@@ -37,6 +39,17 @@ namespace Barcode {
*/
int convertSourceMV2Zbar(mv_source_h mvSource, zbar::Image& zbarSource);
+/**
+ * @brief This function converts media vision image handle to cv::Mat with gray color.
+ *
+ * @since_tizen 6.5
+ * @param [in] mvSource Media vision image handle
+ * @param [out] cv::Mat
+ * @return @c MEDIA_VISION_ERROR_NONE on success,
+ otherwise a negative error value
+ */
+int convertSourceMV2GrayCV(mv_source_h mvSource, cv::Mat& cvSource);
+
} /* Barcode */
} /* MediaVision */
diff --git a/mv_barcode/barcode_detector/src/BarcodeUtils.cpp b/mv_barcode/barcode_detector/src/BarcodeUtils.cpp
index b8c70d97..6f4c7d21 100644
--- a/mv_barcode/barcode_detector/src/BarcodeUtils.cpp
+++ b/mv_barcode/barcode_detector/src/BarcodeUtils.cpp
@@ -103,5 +103,105 @@ int convertSourceMV2Zbar(mv_source_h mvSource, zbar::Image& zbarSource)
return err;
}
+int convertSourceMV2GrayCV(mv_source_h mvSource, cv::Mat& cvSource)
+{
+ MEDIA_VISION_INSTANCE_CHECK(mvSource);
+
+ int depth = CV_8U; // Default depth. 1 byte for channel.
+ unsigned int channelsNumber = 0u;
+ unsigned int width = 0u, height = 0u;
+ unsigned int bufferSize = 0u;
+ unsigned char *buffer = NULL;
+
+ mv_colorspace_e colorspace = MEDIA_VISION_COLORSPACE_INVALID;
+
+ MEDIA_VISION_ASSERT(mv_source_get_width(mvSource, &width),
+ "Failed to get the width.");
+ MEDIA_VISION_ASSERT(mv_source_get_height(mvSource, &height),
+ "Failed to get the height.");
+ MEDIA_VISION_ASSERT(mv_source_get_colorspace(mvSource, &colorspace),
+ "Failed to get the colorspace.");
+ MEDIA_VISION_ASSERT(mv_source_get_buffer(mvSource, &buffer, &bufferSize),
+ "Failed to get the buffer size.");
+
+ int conversionType = -1; /* Type of conversion from given colorspace to gray */
+ switch(colorspace) {
+ case MEDIA_VISION_COLORSPACE_INVALID:
+ LOGE("Error: mv_source has invalid colorspace.");
+ return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+ case MEDIA_VISION_COLORSPACE_Y800:
+ channelsNumber = 1;
+ /* Without convertion */
+ break;
+ case MEDIA_VISION_COLORSPACE_I420:
+ channelsNumber = 1;
+ height *= 1.5;
+ conversionType = cv::COLOR_YUV2GRAY_I420;
+ break;
+ case MEDIA_VISION_COLORSPACE_NV12:
+ channelsNumber = 1;
+ height *= 1.5;
+ conversionType = cv::COLOR_YUV2GRAY_NV12;
+ break;
+ case MEDIA_VISION_COLORSPACE_YV12:
+ channelsNumber = 1;
+ height *= 1.5;
+ conversionType = cv::COLOR_YUV2GRAY_YV12;
+ break;
+ case MEDIA_VISION_COLORSPACE_NV21:
+ channelsNumber = 1;
+ height *= 1.5;
+ conversionType = cv::COLOR_YUV2GRAY_NV21;
+ break;
+ case MEDIA_VISION_COLORSPACE_YUYV:
+ channelsNumber = 2;
+ conversionType = cv::COLOR_YUV2GRAY_YUYV;
+ break;
+ case MEDIA_VISION_COLORSPACE_UYVY:
+ channelsNumber = 2;
+ conversionType = cv::COLOR_YUV2GRAY_UYVY;
+ break;
+ case MEDIA_VISION_COLORSPACE_422P:
+ channelsNumber = 2;
+ conversionType = cv::COLOR_YUV2GRAY_Y422;
+ break;
+ case MEDIA_VISION_COLORSPACE_RGB565:
+ channelsNumber = 2;
+ conversionType = cv::COLOR_BGR5652GRAY;
+ break;
+ case MEDIA_VISION_COLORSPACE_RGB888:
+ channelsNumber = 3;
+ conversionType = cv::COLOR_RGB2GRAY;
+ break;
+ case MEDIA_VISION_COLORSPACE_RGBA:
+ channelsNumber = 4;
+ conversionType = cv::COLOR_RGBA2GRAY;
+ break;
+ default:
+ LOGE("Error: mv_source has unsupported colorspace.");
+ return MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT;
+ }
+
+ if (conversionType == -1) {/* Without conversion */
+ cvSource = cv::Mat(cv::Size(width, height),
+ CV_MAKETYPE(depth, channelsNumber), buffer).clone();
+ } else {/* With conversion */
+ /* Class for representation the given image as cv::Mat before conversion */
+ cv::Mat origin;
+
+ try {
+ origin = cv::Mat(cv::Size(width, height),
+ CV_MAKETYPE(depth, channelsNumber), buffer);
+
+ cv::cvtColor(origin, cvSource, conversionType);
+ } catch (const cv::Exception &e) {
+ LOGE("Failed to cvtColor with %s", e.what());
+ return MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT;
+ }
+ }
+
+ return MEDIA_VISION_ERROR_NONE;
+}
+
} /* Barcode */
} /* MediaVision */
diff --git a/mv_barcode/barcode_detector/src/mv_barcode_detect_open.cpp b/mv_barcode/barcode_detector/src/mv_barcode_detect_open.cpp
index 0d4be8e8..54dee63a 100644
--- a/mv_barcode/barcode_detector/src/mv_barcode_detect_open.cpp
+++ b/mv_barcode/barcode_detector/src/mv_barcode_detect_open.cpp
@@ -20,7 +20,9 @@
#include "BarcodeUtils.h"
#include <mv_private.h>
-
+#include <vector>
+#include <opencv2/core/core.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
#include <zbar.h>
using namespace MediaVision::Barcode;
@@ -35,29 +37,16 @@ int mv_barcode_detect_open(
if (!source || !detect_cb)
return MEDIA_VISION_ERROR_INVALID_PARAMETER;
- zbar::Image image;
- int err = convertSourceMV2Zbar(source, image);
- if (err != MEDIA_VISION_ERROR_NONE) {
- LOGW("convertSourceMV2Zbar failed");
- return err;
- }
-
- zbar::Image greyImage = image.convert("Y800");
- if (!greyImage.get_data()) {
- LOGE("fail to image convert by zbar");
- return MEDIA_VISION_ERROR_INVALID_OPERATION;
- }
-
- greyImage.set_crop(roi.point.x, roi.point.y, roi.width, roi.height);
zbar::ImageScanner scanner;
int target_val;
- err = mv_engine_config_get_int_attribute(
+ int err = mv_engine_config_get_int_attribute(
engine_cfg,
"MV_BARCODE_DETECT_ATTR_TARGET",
&target_val);
if (err != MEDIA_VISION_ERROR_NONE || engine_cfg == NULL) {
- LOGW("mv_engine_config_get_int_attribute failed");
+ LOGW("mv_engine_config_get_int_attribute failed."
+ "MV_BARCODE_DETECT_ATTR_TARGET_ALL is used as default");
/* Default value */
target_val = 0;
}
@@ -110,65 +99,164 @@ int mv_barcode_detect_open(
LOGW("Unavailable target value %d", target_val);
}
- int numberOfBarcodes = scanner.scan(greyImage);
- LOGI("ZBar scanner has found %i barcodes on the mv_source_h",
- numberOfBarcodes);
- mv_quadrangle_s *barcodeLocations = NULL;
- mv_barcode_type_e *types = NULL;
-
- if (numberOfBarcodes == 0) {
- LOGI("Call the detect callback for 0 detected barcodes");
- detect_cb(source, engine_cfg, barcodeLocations, NULL,
- types, numberOfBarcodes, user_data);
- return MEDIA_VISION_ERROR_NONE;
- } else if (numberOfBarcodes < 0) {
- LOGW("Incorrect number of barcodes (%i), detection is terminated",
- numberOfBarcodes);
- return MEDIA_VISION_ERROR_INTERNAL;
+ int rotateDegree = 0;
+ int rotateNumber = 0;
+ int rotateDirection = 0;
+ bool isEnhancementMode = false;
+ if (engine_cfg != NULL) {
+ err = mv_engine_config_get_int_attribute(
+ engine_cfg,
+ MV_BARCODE_DETECT_ATTR_ROTATION_DEGREES,
+ &rotateDegree);
+ if (err != MEDIA_VISION_ERROR_NONE) {
+ LOGE("mv_engine_config_get_int_attribute failed to get MV_BARCODE_DETECT_ATTR_ROTATE_DEGREES");
+ return err;
+ }
+
+ err = mv_engine_config_get_int_attribute(
+ engine_cfg,
+ MV_BARCODE_DETECT_ATTR_ROTATION_COUNT,
+ &rotateNumber);
+ if (err != MEDIA_VISION_ERROR_NONE) {
+ LOGE("mv_engine_config_get_int_attribute failed to get MV_BARCODE_DETECT_ATTR_ROTATE_COUNT");
+ return err;
+ }
+
+ err = mv_engine_config_get_int_attribute(
+ engine_cfg,
+ MV_BARCODE_DETECT_ATTR_ROTATION_DIRECTION,
+ &rotateDirection);
+ if (err != MEDIA_VISION_ERROR_NONE) {
+ LOGE("mv_engine_config_get_int_attribute failed to get MV_BARCODE_DETECT_ATTR_ROTATE_DIRECTION");
+ return err;
+ }
+
+ err = mv_engine_config_get_bool_attribute(
+ engine_cfg,
+ MV_BARCODE_DETECT_ATTR_USE_ENHANCEMENT,
+ &isEnhancementMode);
+ if (err != MEDIA_VISION_ERROR_NONE) {
+ LOGE("mv_engine_config_get_bool_attribute failed to get MV_BARCODE_DETECT_ATTR_USE_ENHANCEMENT");
+ return err;
+ }
}
- const char **messagesArray = new const char*[numberOfBarcodes];
- barcodeLocations = new mv_quadrangle_s[numberOfBarcodes];
- types = new mv_barcode_type_e[numberOfBarcodes];
+ cv::Mat graySource;
+ cv::Mat rotMat, rotBuffer;
+ err = convertSourceMV2GrayCV(source, graySource);
+ if (err != MEDIA_VISION_ERROR_NONE) {
+ LOGE("Failed to convertSourceMV2GrayCV[%d]", err);
+ return err;
+ }
- int i = 0;
- /* extract results and prepare them for callback passing */
- for (zbar::SymbolIterator symbol = greyImage.symbol_begin();
- symbol != greyImage.symbol_end();
- ++symbol, ++i) {
- Barcode curBarcode(*symbol);
+ cv::Mat rawBuffer = graySource(cv::Rect(roi.point.x, roi.point.y, roi.width, roi.height));
- size_t messageLength = curBarcode.getMessage().size();
- char *curMessage = new char[messageLength + 1];
- curBarcode.getMessage().copy(curMessage, messageLength);
- curMessage[messageLength] = '\0';
- messagesArray[i] = curMessage;
+ if (isEnhancementMode) {
+ cv::Mat clacheBuffer;
+ cv::Ptr<cv::CLAHE> clache = cv::createCLAHE();
+ clache->setClipLimit(2.0);
+ clache->apply(rawBuffer, clacheBuffer);
- types[i] = curBarcode.getType();
+ cv::threshold(clacheBuffer, rawBuffer, 240, 255, cv::THRESH_TRUNC | cv::THRESH_OTSU);
+ }
- LOGI("barcode type: %d with message %s", types[i], curMessage);
- int err = curBarcode.calculateLocation(barcodeLocations[i]);
- if (err != MEDIA_VISION_ERROR_NONE) {
- LOGW("Can't determine location for barcode, detection is terminated");
- for (int j = 0; j <= i; ++j)
+ std::vector<std::string> barcodeMessages;
+ std::vector<mv_quadrangle_s> barcodeLocations;
+ std::vector<mv_barcode_type_e> barcodeTypes;
+ zbar::Image _image;
+
+ LOGI("%d numbers with %d degree to %d direction", rotateNumber, rotateDegree, rotateDirection);
+
+ if (rotateDirection == MV_BARCODE_DETECT_ATTR_ROTATION_ALL)
+ rotateNumber *= 2;
+
+ rotateNumber++;
+
+ int degree = 0;
+ for (int i = 0; i < rotateNumber; ++i) {
+ if (rotateDirection == MV_BARCODE_DETECT_ATTR_ROTATION_CLOCKWISE) {
+ degree = -1 * rotateDegree * i;
+ } else if (rotateDirection == MV_BARCODE_DETECT_ATTR_ROTATION_COUNTER_CLOCKWISE) {
+ degree = rotateDegree * i;
+ } else { // MV_BARCODE_DETECT_ATTR_ROTATE_ALL
+ if (i%2) {
+ degree = -1 * rotateDegree * ((i+1)/2);
+ } else {
+ degree = rotateDegree * (i/2);
+ }
+ }
+
+ rotMat = cv::getRotationMatrix2D(cv::Point((roi.width/2), (roi.height/2)), degree, 1.0);
+ warpAffine(rawBuffer, rotBuffer, rotMat, rawBuffer.size());
+
+ _image.set_format("Y800");
+ _image.set_size(rotBuffer.cols, rotBuffer.rows);
+ _image.set_data(rotBuffer.data, rotBuffer.total() * rotBuffer.elemSize());
+
+ LOGW("%p", _image.get_data());
+ if (!_image.get_data()) {
+ LOGE("fail to get image data");
+ return MEDIA_VISION_ERROR_INVALID_OPERATION;
+ }
+
+ int numberOfBarcodes = scanner.scan(_image);
+ if (numberOfBarcodes <= 0)
+ continue;
+
+ LOGI("[rot:%d]: %d barcodes detected", i, numberOfBarcodes);
+ barcodeMessages.clear();
+ barcodeTypes.clear();
+ barcodeLocations.clear();
+ bool isDetected = true;
+ for (zbar::SymbolIterator symbol = _image.symbol_begin();
+ symbol != _image.symbol_end(); ++symbol) {
+
+ Barcode curBarcode(*symbol);
+ mv_quadrangle_s location;
+ int err = curBarcode.calculateLocation(location);
+ if (err != MEDIA_VISION_ERROR_NONE) {
+ isDetected = false;
+ break;
+ }
+
+ barcodeMessages.push_back(curBarcode.getMessage());
+ barcodeTypes.push_back(curBarcode.getType());
+ barcodeLocations.push_back(location);
+ }
+
+ if (isDetected) {
+ LOGI("Call the detect callback for %d detected barcodes", numberOfBarcodes);
+ const char **messagesArray = new const char*[numberOfBarcodes];
+ mv_barcode_type_e *types = new mv_barcode_type_e[numberOfBarcodes];
+ mv_quadrangle_s *locations = new mv_quadrangle_s[numberOfBarcodes];
+
+ for (int i = 0; i < numberOfBarcodes; ++i) {
+
+ size_t messageLength = barcodeMessages[i].size();
+ char *curMessage = new char[messageLength + 1];
+ barcodeMessages[i].copy(curMessage, messageLength);
+ curMessage[messageLength] = '\0';
+ messagesArray[i] = curMessage;
+
+ types[i] = barcodeTypes[i];
+ locations[i] = barcodeLocations[i];
+ LOGI("%d: barcode with %s with type %d", i, messagesArray[i], types[i]);
+ }
+ detect_cb(source, engine_cfg, locations, messagesArray, types,
+ numberOfBarcodes, user_data);
+ LOGI("Clean the memory from barcodes messages and types");
+ for (int j = 0; j < numberOfBarcodes; ++j)
delete[] messagesArray[j];
delete[] messagesArray;
- delete[] barcodeLocations;
+ delete[] locations;
delete[] types;
- return err;
+
+ return MEDIA_VISION_ERROR_NONE;
}
}
-
- LOGI("Call the detect callback for %i detected barcodes", numberOfBarcodes);
- detect_cb(source, engine_cfg, barcodeLocations, messagesArray, types,
- numberOfBarcodes, user_data);
-
- LOGI("Clean the memory from barcodes messages, locations and types");
- for (int j = 0; j < numberOfBarcodes; ++j)
- delete[] messagesArray[j];
- delete[] messagesArray;
- delete[] barcodeLocations;
- delete[] types;
+ LOGI("Call the detect callback for 0 detected barcodes");
+ detect_cb(source, engine_cfg, NULL, NULL,
+ NULL, 0, user_data);
return MEDIA_VISION_ERROR_NONE;
}