add zbar to scan barcodes in video capture feed
This commit is contained in:
parent
7b9549d413
commit
cc9aa231ff
3
Makefile
3
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 : CPP_FLAGS = $(CFLAGS) --std=c++17
|
||||||
linux : LFLAGS = $(shell $(SDLCONFIG) --libs) -lpthread -lGL -lGLESv2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lcurl -lstdc++fs \
|
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 \
|
-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) \
|
linux : $(GLEW_DIR)glew.o $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) \
|
||||||
$(SFW_O_FILES) $(GAME_O_FILES)
|
$(SFW_O_FILES) $(GAME_O_FILES)
|
||||||
$(CREATE_FONT_SYMLINK)
|
$(CREATE_FONT_SYMLINK)
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
{
|
{
|
||||||
"json-save": true,
|
"json-save": true,
|
||||||
"json-save-directory": "local/scans",
|
"json-save-directory": "local/scans",
|
||||||
"barcode": "400063314395",
|
"barcode": "",
|
||||||
"capture-device": "/dev/video0"
|
"capture-device": "/dev/video0"
|
||||||
},
|
},
|
||||||
"api":
|
"api":
|
||||||
|
@ -50,8 +50,8 @@
|
||||||
"best-buy-api-key": "vAC23XA5YWBzaYiGtOkoNlXZ",
|
"best-buy-api-key": "vAC23XA5YWBzaYiGtOkoNlXZ",
|
||||||
"giantbomb-api-key": "91a395231f4e1fd9f9ba8840c52a61cda343cd70",
|
"giantbomb-api-key": "91a395231f4e1fd9f9ba8840c52a61cda343cd70",
|
||||||
"nutronix-enabled": false,
|
"nutronix-enabled": false,
|
||||||
"edamam-enabled": false,
|
"edamam-enabled": true,
|
||||||
"open-food-enabled": false,
|
"open-food-enabled": true,
|
||||||
"best-buy-enabled": true
|
"best-buy-enabled": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "Pudding.hpp"
|
#include "Pudding.hpp"
|
||||||
|
|
||||||
|
/* Launch the Pudding instance's mainloop */
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Pudding pudding = Pudding();
|
Pudding pudding = Pudding();
|
||||||
|
@ -24,9 +25,12 @@ int main()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize a Pudding instance */
|
||||||
Pudding::Pudding()
|
Pudding::Pudding()
|
||||||
{
|
{
|
||||||
|
/* subscribe to command events */
|
||||||
get_delegate().subscribe(&Pudding::respond, this);
|
get_delegate().subscribe(&Pudding::respond, this);
|
||||||
|
/* initialize an opencv capture device for getting images from an attached camera */
|
||||||
int device_id = 0;
|
int device_id = 0;
|
||||||
capture.open(device_id);
|
capture.open(device_id);
|
||||||
std::stringstream message;
|
std::stringstream message;
|
||||||
|
@ -41,10 +45,14 @@ Pudding::Pudding()
|
||||||
message << "failed to open video capture device ID #" << device_id;
|
message << "failed to open video capture device ID #" << device_id;
|
||||||
}
|
}
|
||||||
log(message.str());
|
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();
|
load_sdl_context();
|
||||||
|
items.reserve(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Respond to key press events
|
/* Respond to command events */
|
||||||
void Pudding::respond(SDL_Event& event)
|
void Pudding::respond(SDL_Event& event)
|
||||||
{
|
{
|
||||||
if (get_delegate().compare(event, "up"))
|
if (get_delegate().compare(event, "up"))
|
||||||
|
@ -90,6 +98,7 @@ void Pudding::add_item(const std::string& upc)
|
||||||
incorporate_best_buy_api(item);
|
incorporate_best_buy_api(item);
|
||||||
}
|
}
|
||||||
items.push_back(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
|
/* 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];
|
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)
|
// 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, "") != "")
|
if (product.value(key, "") != "")
|
||||||
{
|
{
|
||||||
|
@ -366,10 +375,13 @@ void Pudding::update()
|
||||||
/* reload the config file every frame to check for changes */
|
/* reload the config file every frame to check for changes */
|
||||||
get_root()->configuration.load("config.json");
|
get_root()->configuration.load("config.json");
|
||||||
get_root()->configuration.merge();
|
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"];
|
current_config_barcode = get_configuration()["scan"]["barcode"];
|
||||||
add_item(current_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 */
|
/* draw the current item image to the left half of the screen if items are available */
|
||||||
Box video_box = get_window_box();
|
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_UpdateTexture(texture, nullptr, static_cast<void*>(capture_frame.data), capture_frame.step1());
|
||||||
SDL_RenderCopyF(get_renderer(), texture, nullptr, &video_box);
|
SDL_RenderCopyF(get_renderer(), texture, nullptr, &video_box);
|
||||||
SDL_DestroyTexture(texture);
|
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
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "opencv2/core.hpp"
|
#include "opencv2/core.hpp"
|
||||||
#include "opencv2/videoio.hpp"
|
#include "opencv2/videoio.hpp"
|
||||||
#include "opencv2/highgui.hpp"
|
#include "opencv2/highgui.hpp"
|
||||||
|
#include "opencv2/imgproc.hpp"
|
||||||
#include "zbar.h"
|
#include "zbar.h"
|
||||||
#include "Game.hpp"
|
#include "Game.hpp"
|
||||||
#include "Sprite.hpp"
|
#include "Sprite.hpp"
|
||||||
|
@ -34,11 +35,12 @@ private:
|
||||||
const std::string BEST_BUY_API_URL_2 = ")?format=json&apiKey=";
|
const std::string BEST_BUY_API_URL_2 = ")?format=json&apiKey=";
|
||||||
const std::string NUTRONIX_NOT_FOUND = "resource not found";
|
const std::string NUTRONIX_NOT_FOUND = "resource not found";
|
||||||
const std::string GIANTBOMB_API_URL = "https://www.giantbomb.com/api/release/?api_key=";
|
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;
|
std::vector<Item> items;
|
||||||
int previously_captured_frame_index = -1, current_item_index = 0;
|
int current_item_index = 0;
|
||||||
cv::VideoCapture capture;
|
cv::VideoCapture capture;
|
||||||
cv::Mat capture_frame;
|
cv::Mat capture_frame;
|
||||||
|
zbar::ImageScanner image_scanner;
|
||||||
|
|
||||||
void incorporate_open_food_api(Item&);
|
void incorporate_open_food_api(Item&);
|
||||||
void incorporate_nutronix_api(Item&);
|
void incorporate_nutronix_api(Item&);
|
||||||
|
|
Loading…
Reference in New Issue