add zbar to scan barcodes in video capture feed

This commit is contained in:
frank 2021-06-28 16:30:12 -04:00
parent 7b9549d413
commit cc9aa231ff
4 changed files with 50 additions and 13 deletions

View File

@ -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)

View File

@ -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
}
}

View File

@ -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<void*>(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<void*>(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;
}
}

View File

@ -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<Item> 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&);