From cc9aa231ff47d27aea3ef991bc8dd46f64dec431 Mon Sep 17 00:00:00 2001 From: frank <420@shampoo.ooo> Date: Mon, 28 Jun 2021 16:30:12 -0400 Subject: [PATCH] add zbar to scan barcodes in video capture feed --- Makefile | 3 ++- config.json | 6 +++--- src/Pudding.cpp | 48 +++++++++++++++++++++++++++++++++++++++++------- src/Pudding.hpp | 6 ++++-- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 35204aa..c3f31c2 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,8 @@ linux : CFLAGS = -g3 -Wall -Wextra -Og -c -I$(SFW_LIB_DIR) -I$(SFW_SRC_DIR) $(SD linux : CPP_FLAGS = $(CFLAGS) --std=c++17 linux : LFLAGS = $(shell $(SDLCONFIG) --libs) -lpthread -lGL -lGLESv2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lcurl -lstdc++fs \ -L/home/frank/local/opencv/lib -Wl,-rpath,/home/frank/local/opencv/lib -Wl,--enable-new-dtags -lopencv_videoio -lopencv_core \ - -lopencv_highgui + -lopencv_highgui -lopencv_imgproc \ + -L/home/frank/local/zbar/lib -Wl,-rpath,/home/frank/local/zbar/lib -Wl,--enable-new-dtags -lzbar linux : $(GLEW_DIR)glew.o $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) \ $(SFW_O_FILES) $(GAME_O_FILES) $(CREATE_FONT_SYMLINK) diff --git a/config.json b/config.json index 44ca451..d411d4c 100644 --- a/config.json +++ b/config.json @@ -37,7 +37,7 @@ { "json-save": true, "json-save-directory": "local/scans", - "barcode": "400063314395", + "barcode": "", "capture-device": "/dev/video0" }, "api": @@ -50,8 +50,8 @@ "best-buy-api-key": "vAC23XA5YWBzaYiGtOkoNlXZ", "giantbomb-api-key": "91a395231f4e1fd9f9ba8840c52a61cda343cd70", "nutronix-enabled": false, - "edamam-enabled": false, - "open-food-enabled": false, + "edamam-enabled": true, + "open-food-enabled": true, "best-buy-enabled": true } } diff --git a/src/Pudding.cpp b/src/Pudding.cpp index d6f35c7..41bf92f 100644 --- a/src/Pudding.cpp +++ b/src/Pudding.cpp @@ -16,6 +16,7 @@ #include "Pudding.hpp" +/* Launch the Pudding instance's mainloop */ int main() { Pudding pudding = Pudding(); @@ -24,9 +25,12 @@ int main() return 0; } +/* Initialize a Pudding instance */ Pudding::Pudding() { + /* subscribe to command events */ get_delegate().subscribe(&Pudding::respond, this); + /* initialize an opencv capture device for getting images from an attached camera */ int device_id = 0; capture.open(device_id); std::stringstream message; @@ -41,10 +45,14 @@ Pudding::Pudding() message << "failed to open video capture device ID #" << device_id; } log(message.str()); + /* initialize a zbar image scanner for reading barcodes of any format */ + image_scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); + /* use sdl context for now */ load_sdl_context(); + items.reserve(10); } -// Respond to key press events +/* Respond to command events */ void Pudding::respond(SDL_Event& event) { if (get_delegate().compare(event, "up")) @@ -90,6 +98,7 @@ void Pudding::add_item(const std::string& upc) incorporate_best_buy_api(item); } items.push_back(item); + increment_item_index(); } /* Look for item upc in the Open Food API, and use the result to fill out item properties if found @@ -199,7 +208,7 @@ void Pudding::incorporate_best_buy_api(Item& item) { nlohmann::json product = json["products"][0]; // look up image (for games this is box art) and "alternate views image" (for games this is a screen shot) - for (std::string key : {"image", "alternateViewsImage"}) + for (std::string key : {"alternateViewsImage", "image"}) { if (product.value(key, "") != "") { @@ -366,10 +375,13 @@ void Pudding::update() /* reload the config file every frame to check for changes */ get_root()->configuration.load("config.json"); get_root()->configuration.merge(); - if (current_barcode != get_configuration()["scan"]["barcode"]) + if (current_config_barcode != get_configuration()["scan"]["barcode"]) { - current_barcode = get_configuration()["scan"]["barcode"]; - add_item(current_barcode); + current_config_barcode = get_configuration()["scan"]["barcode"]; + current_barcode = current_config_barcode; + std::stringstream message; + message << "read new barcode from config " << current_barcode; + log(message.str()); } /* draw the current item image to the left half of the screen if items are available */ Box video_box = get_window_box(); @@ -391,11 +403,33 @@ void Pudding::update() SDL_UpdateTexture(texture, nullptr, static_cast(capture_frame.data), capture_frame.step1()); SDL_RenderCopyF(get_renderer(), texture, nullptr, &video_box); SDL_DestroyTexture(texture); - previously_captured_frame_index = capture.get(cv::CAP_PROP_POS_FRAMES); + /* scan with zbar */ + cv::Mat gray; + cv::cvtColor(capture_frame, gray, cv::COLOR_BGR2GRAY); + zbar::Image query_image(gray.cols, gray.rows, "Y800", static_cast(gray.data), gray.cols * gray.rows); + int result = image_scanner.scan(query_image); + if (result > 0) + { + for (zbar::Image::SymbolIterator symbol = query_image.symbol_begin(); symbol != query_image.symbol_end(); ++symbol) + { + std::stringstream message; + message << "camera scanned " << symbol->get_type_name() << " symbol " << symbol->get_data(); + log(message.str()); + current_camera_barcode = symbol->get_data(); + current_barcode = current_camera_barcode; + } + } + query_image.set_data(nullptr, 0); } else { - log("video capture device frame empty"); + debug("video capture device frame empty"); } } + /* add a new item if a new barcode was scanned or entered */ + if (current_barcode != previous_barcode) + { + add_item(current_barcode); + previous_barcode = current_barcode; + } } diff --git a/src/Pudding.hpp b/src/Pudding.hpp index 2d418cf..70cbc1b 100644 --- a/src/Pudding.hpp +++ b/src/Pudding.hpp @@ -14,6 +14,7 @@ #include "opencv2/core.hpp" #include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" +#include "opencv2/imgproc.hpp" #include "zbar.h" #include "Game.hpp" #include "Sprite.hpp" @@ -34,11 +35,12 @@ private: const std::string BEST_BUY_API_URL_2 = ")?format=json&apiKey="; const std::string NUTRONIX_NOT_FOUND = "resource not found"; const std::string GIANTBOMB_API_URL = "https://www.giantbomb.com/api/release/?api_key="; - std::string current_barcode; + std::string current_barcode, previous_barcode, current_config_barcode, current_camera_barcode; std::vector items; - int previously_captured_frame_index = -1, current_item_index = 0; + int current_item_index = 0; cv::VideoCapture capture; cv::Mat capture_frame; + zbar::ImageScanner image_scanner; void incorporate_open_food_api(Item&); void incorporate_nutronix_api(Item&);