예제 #1
0
def summarise_watson_img(src, options=False):
    '''
    IBM Bluemix service
    intersted in default clasifier: images.classifiers.classes 
    '''
    import json
    from watson_developer_cloud import VisualRecognitionV3 as VisualRecognition
    
    classifier = VisualRecognition( '2016-05-20', \
    api_key=config.IBM['credentials']['api_key'])

    result = classifier.classify(images_url=src)
    # debug
    print(json.dumps(result, indent=2))

    return result
예제 #2
0
def search(request):
    if (request.method == 'POST'):
        f = searchform(request.POST, request.FILES)
        if not f.is_valid():
            return render(request, 'objects/home.html', {'f': f})
        userobj = f.save(commit=False)
        userobj.save()
        visual_recognition = VisualRecognition(
            '2016-09-30', api_key='7a85ea3ccce43d03daea662cb7b6b7236aeb4dd0')
        img = visual_recognition.classify(
            images_url="http://127.0.0.1:8000/images/9/")
        print(json.dumps(img, indent=2))

        p = img.images.classifiers.classes
        for i in p:
            d = i['class']
            tags.objects.create(tags_value=d, parent=userobj)
        return HttpResponse('OK')

    if (request.method == 'GET'):
        f = searchform()
        return render(request, 'objects/home.html', {'f': f})
예제 #3
0
print("##########################################\n")
'''
img_urls = {}
for i in range(len(datasets)):
    if i % 2 == 1:
        continue
    data = datasets[i]
    for i in range(1200):
        for painting in data[i]:
            img_urls[painting.imageFilename()] = painting.imageURL

print len(img_urls)

objects = {}
counter = 0
for img_id, url in img_urls.iteritems():
    print counter
    try:
        img_info = visual_recognition.classify(images_url=url)
        all_classes = img_info["images"][0]["classifiers"][0]["classes"]
        classes_lst = []
        for c in all_classes:
            classes_lst.append(c["class"])
        objects[img_id] = classes_lst
        counter += 1
    except:
        print "Hit limit"
        break

npy.save('image_objects.npy', objects)
import json
from os.path import join, dirname
from os import environ
from watson_developer_cloud import VisualRecognitionV3 as VisualRecognition
#31e589a7ae4990a6261e68d8b2931acf5145b973 - alvaro - junto
#37ff1e95c9da3f5e5161d6f49b0139469c087f8d . watsonR - separados
visual_recognition = VisualRecognition(
    '2016-05-20', api_key='37ff1e95c9da3f5e5161d6f49b0139469c087f8d')

data = json.loads(
    json.dumps(visual_recognition.classify(
        owners="me",
        images_url=
        "https://scontent-mia1-2.xx.fbcdn.net/v/t34.0-12/15327550_10211547072255521_2026008890_n.jpg?oh=de2807a23063390a95628815543e73e9&oe=5847146E"
    ),
               indent=2))
#print data
if (len(data['images'][0]['classifiers']) > 0):
    for i in data['images'][0]['classifiers'][0]['classes']:
        print i['class'] + ' = ' + str(i['score'])
else:
    print 'no se ha punteado con ninguno de los valores de las dos clases'
예제 #5
0
camera = picamera.PiCamera()

if not os.path.exists(directory):
    os.makedirs(directory)

zipf = zipfile.ZipFile('image.zip', 'w', zipfile.ZIP_DEFLATED)
for i in range(10):
    filePath = 'image/' + str(i) + '.jpg'
    camera.capture(filePath)
    sleep(0.1)
    zipf.write(filePath, os.path.basename(filePath))
zipf.close()

print "Please Wait..Image Processing Started"

data = json.dumps(visual_recognition.classify(file, url, classifier_ids),
                  indent=2)

data = json.loads(data)

print data

names = {}

if data.has_key("images"):
    for i in range(len(data["images"])):
        if (len(data["images"][i]["classifiers"]) > 0):
            classifiers = data["images"][i]["classifiers"][0]
            if (classifiers.has_key("name")):
                if (classifiers["name"] == "face"):
                    if (classifiers["classes"][0]["score"] > 0.5):
예제 #6
0
class ImageClassifier:
    def __init__(self):
        self.vr = VisualRecognition(
            version='2016-05-20',
            api_key='7b851fccf7f17a35fc7569a5dad6e1eb4f650f70')

    def classify(self, imgFile):
        rgb = io.imread(imgFile)
        aspect_ratio = len(rgb) / len(rgb[1])
        rgb = transform.resize(rgb, [int(1000 * aspect_ratio), 1000])
        img = color.rgb2lab(rgb)
        thresholded = np.logical_and(
            *[img[..., i] > t for i, t in enumerate([40, 0, 0])])
        '''
        fig, ax = plt.subplots(ncols=2)
        ax[0].imshow(rgb);         ax[0].axis('off')
        ax[1].imshow(thresholded); ax[1].axis('off')
        plt.show()
        '''

        X = np.argwhere(thresholded)[::5]
        X = np.fliplr(X)

        db = DBSCAN(eps=50, min_samples=200).fit(X)
        core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
        core_samples_mask[db.core_sample_indices_] = True
        labels = db.labels_

        # Number of clusters in labels, ignoring noise if present.
        n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)

        print('Estimated number of clusters: %d' % n_clusters_)
        unique_labels = set(labels)
        '''
        # #############################################################################
        # Plot result
        import matplotlib.pyplot as plt

        # Black removed and is used for noise instead.
        colors = [plt.cm.Spectral(each)
                  for each in np.linspace(0, 1, len(unique_labels))]
        for k, col in zip(unique_labels, colors):
            if k == -1:
                # Black used for noise.
                col = [0, 0, 0, 1]

            class_member_mask = (labels == k)

            xy = X[class_member_mask & core_samples_mask]
            plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
                     markeredgecolor='k', markersize=14)

            xy = X[class_member_mask & ~core_samples_mask]
            plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
                     markeredgecolor='k', markersize=6)

        plt.title('Estimated number of clusters: %d' % n_clusters_)
        plt.show()



        x = edge_roberts.sum(axis=0)
        x = x - np.min(x[np.nonzero(x)])
        averageVal = x.mean()
        x = x - 5
        x[x < (averageVal / 6)] = 0

        y = range(len(img[1]))
        plt.plot(y, x)


        X = np.array(list(zip(x,np.zeros(len(x)))), dtype=np.int)
        bandwidth = estimate_bandwidth(X, quantile=0.25)
        ms = MeanShift(bandwidth=bandwidth, bin_seeding=True)
        ms.fit(X)
        labels = ms.labels_
        cluster_centers = ms.cluster_centers_

        labels_unique = np.unique(labels)
        n_clusters_ = len(labels_unique)
        '''

        cropped_images = []
        unique_labels.remove(-1)
        col = 0

        for k in unique_labels:
            #my_members = labels == k
            #members = X[my_members, 0]
            left = min(X[labels == k][:, 0])
            right = max(X[labels == k][:, 0])
            padding = 20
            if left > padding:
                left = left - padding
            if right < len(img[1]) - padding:
                right = right + padding
            cropped_images.append(rgb[0:len(img), left:right])

        # save each cropped image by its index number
        myzip = ZipFile('cutimgs.zip', 'w', zipfile.ZIP_DEFLATED)
        for c, cropped_image in enumerate(cropped_images):
            io.imsave(str(c) + ".png", cropped_image)
            myzip.write(str(c) + ".png")

        myzip.printdir()
        myzip.close()

        for c, cropped_image in enumerate(cropped_images):
            os.remove(str(c) + ".png")

        with open('cutimgs.zip', 'rb') as img:
            param = {'classifier_ids': "foodtest_843163904"}
            params = json.dumps(param)
            response = self.vr.classify(images_file=img, parameters=params)
            classes = []
            for image in response['images']:
                if (image['classifiers'][0]['classes'][0]['class']
                    ) not in classes:
                    classes.append(
                        (image['classifiers'][0]['classes'][0]['class']))

        os.remove('cutimgs.zip')

        return classes
예제 #7
0
def full(fileName):
    vr = VisualRecognition(version='2016-05-20', api_key='7b851fccf7f17a35fc7569a5dad6e1eb4f650f70')

    rgb = scipy.misc.imread(fileName, mode='RGB')
    aspect_ratio = len(rgb) / len(rgb[1])
    rgb = transform.resize(rgb, [int(1000*aspect_ratio), 1000])
    img = color.rgb2lab(rgb)
    thresholded = np.logical_and(*[img[..., i] > t for i, t in enumerate([40, 0, 0])])
    if (np.sum(thresholded) > (thresholded.size / 2)):
        thresholded = np.invert(thresholded)
        
    X = np.argwhere(thresholded)[::5]
    X = np.fliplr(X)


    db = DBSCAN(eps=25, min_samples=200).fit(X)
    core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
    core_samples_mask[db.core_sample_indices_] = True
    labels = db.labels_

    # Number of clusters in labels, ignoring noise if present.
    n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)

    print('Estimated number of clusters: %d' % n_clusters_)



    unique_labels = set(labels)


    cropped_images = []
    unique_labels.remove(-1)
    col=0

    for k in unique_labels:
        #my_members = labels == k
        #members = X[my_members, 0]
        left = min(X[labels==k][:,0])
        right = max(X[labels==k][:,0])
        padding = 20
        if left > padding:
            left = left - padding
        if right < len(img[1]) - padding:
            right = right + padding
        cropped_images.append(rgb[0:len(img), left:right])	

    # save each cropped image by its index number
    myzip = ZipFile('test.zip', 'w',zipfile.ZIP_DEFLATED)
    for c, cropped_image in enumerate(cropped_images):
        io.imsave(str(c) + ".png", cropped_image)
        myzip.write(str(c) + ".png")    

    myzip.printdir()
    myzip.close()  

    for c, cropped_image in enumerate(cropped_images):
        os.remove(str(c) + ".png")

    classes = []
    with open('test.zip', 'rb') as img:
        param = {'classifier_ids':"foodtest_1606116153"}
        params = json.dumps(param)
        response = vr.classify(images_file=img, parameters=params)

        for image in response['images']:
            max_score = 0
            max_class = ""
            for classifier in image['classifiers']:
                for classif in classifier['classes']:
                    if (classif['score'] > max_score):
                        max_class = classif['class']
            
            
            if max_class:
                max_class = max_class.replace('_', ' ')
                if (max_class) not in classes:
                    classes.append(max_class)
                    
        
        
        
    os.remove('test.zip')
    return(classes)
예제 #8
0
class SmartFridge():
    def __init__(self):
        self.context = {}
        self.option_dict = {}
        self.intents = []
        self.entities = []
        self.recipe_options = []
        self.database_cursor = None


        # Reset enviroment variables

        self.context['search_recipe'] = False
        self.context['image_recipe'] = False
        self.context['suggest_dish'] = False
        self.context['yum_sugest'] = False
        self.context['summary'] = False
        self.context['option'] = None
        self.context['cuisine_type'] = None
        self.context['ingredients'] = None
        self.context['intolerances'] = None
        self.context['dish'] = None
        self.context['counter'] = 0
        self.context['insult_counter'] = 0


        # Services initialization

        #  Slack client instance
        self.slack_client = SlackClient(SLACK_BOT_TOKEN)

        # Watson Conversation sevice instance
        self.conversation = Conversation(version = CONVERSATION_VERSION,
                                         username = CONVERSATION_USERNAME,
                                         password = CONVERSATION_PASSWORD,
                                         url = CONVERSATION_URL)

        #  Watson Visual Recognition service instance
        self.visual_recognition = VisualRecognition(version=VISUAL_RECOGNITION_VERSION,
                                                    url=VISUAL_RECOGNITION_URL,
                                                    api_key=VISUAL_RECOGNITION_KEY)
        # Database connection
        self.database_connection(DB_STRING_CONNECTION)



    ######   CONVERSATION MANAGEMENT ########

    # Receives commands directed at the bot and determines if they
    # are valid commands. If so, then acts on the commands. If not,
    # returns back what it needs for clarification.
    def handle_command(self, command):

        response = "Not sure what you mean. Please reword your request"

        print('\n\nINPUT = {}\n'.format(command))

        # Processing of the response
        if command == 'download_file_format_error':
            response = 'The file extension is not valid. Try with JPG or PNG.'
        # Food image recognition
        elif command.startswith('photo'):
            self.send_response('Please, give me a second... :hourglass_flowing_sand:')
            self.context['image_recipe'] = "true"
            response_text, intent, entity=self.update_conversation_context()
            response = self.image_food_recognition()
        else:
            response_text, intent, entity = self.msg_to_conversation(command)
            print('intent = {} '.format(intent))
            print('entity = {} '.format(entity))

            # A suggestion is provide to the user because the required information
            # is not provided by the user after several attempts
            # $yum_sugest
            if(self.context['yum_sugest'] == 'true'):
                self.send_response(response_text)
                response = self.yum_suggestion()

            # $suggest_dish
            elif(self.context['suggest_dish'] == 'true'):
                self.send_response(response_text)
                response = self.suggest_dish()

            # $summary
            elif(self.context['summary'] == 'true'):
                self.send_response(response_text)
                response = self.get_db_summary()

            # $search_recipe
            elif(self.context['search_recipe'] == 'true'):
                self.send_response(response_text)
                response = self.get_recipe()

            # #get_recipe
            elif intent == 'get_recipe':
                if(self.context['search_recipe'] == 'true'):
                    response = self.get_recipe()
                elif(self.context['yum_sugest'] == 'true'):
                    response = self.yum_suggestion()
                else:
                    response= response_text

            # #suggest_dish
            elif intent=='sugest_dish':
                if(self.context['suggest_dish'] == 'true'):
                    response = self.suggest_dish()
                elif(self.context['yum_sugest'] == 'true'):
                    response = self.yum_suggestion()
                else:
                    response = response_text

            # #available_ingredients
            elif intent=='available_ingredients':
                ingredients = self.context['ingredients']
                if ingredients != None:
                    self.send_response(response_text)
                    response = self.get_ingredients_information(ingredients)
                else:
                    self.send_response(response_text)
                    response = self.get_db_summary()

            # #needed_ingredients
            elif intent == 'needed_ingredients':
                response = response_text

            # #select_option
            elif intent == 'select_option':
                option_response = self.select_option()
                if option_response != '':
                    response = option_response
                else:
                    response = response_text

            # #negative_reaction
            elif intent == 'negative_reaction':
                response = response_text

            # #anaything_else
            else:
                response = response_text

        # Send the corresponding response to the user interface (slack)
        self.send_response(response)


    def select_option(self):
        response = ''
        if (self.context['option']!= None) and (len(self.recipe_options) > 0):
            index = self.parse_to_valid_index(self.context['option'])
            if index != None:
                selection = self.recipe_options[index]
                response = 'Ok, good choice! The {} recipe below: '.format(selection)
                response = response + '\n' + self.get_ingredients(self.option_dict[selection])
                self.recipe_options = []

        return response


    def parse_to_valid_index(self, opt):
        value = None

        if opt in range(1, TOTAL_NUMBER_OPTIONS+1):
            value = opt - 1
        else:
            value = None

        return value



    # Prioritizes the use of ingredients that are about to expire
    # Excludes expired products
    def yum_suggestion(self, n_options=6):
        header = 'I have found the following recipes for you:'
        response = ''
        footer = 'Please, provide a valid option from 1 to 6'

        self.recipe_options= []
        self.context['yum_sugest'] = False

        if n_options > 0:

            available_ingredients_options = []
            top_rated_options = []
            trending_options = []

            # n_recipes recipe suggestion by using the n_ingredients with closest expiration date and biggest quantity
            available_ingredients_options = self.get_recipe_options_from_available_ingredients(n_options=2,
                                                                                               n_ingredients=2)

            top_rated_options = self.get_top_rated_recipe_options\
                (n_options=((TOTAL_NUMBER_OPTIONS - len(available_ingredients_options)) // 2)
                           + ((TOTAL_NUMBER_OPTIONS - len(available_ingredients_options)) % 2))

            trending_options = self.get_trending_recipe_options(
                n_options=((TOTAL_NUMBER_OPTIONS - len(available_ingredients_options)) // 2))

            self.recipe_options = available_ingredients_options + top_rated_options + trending_options
            print(self.recipe_options)
            for i, recipe in enumerate(self.recipe_options[:n_options]):
                response = response + '\n' + '[{0}] :  {1}'.format(i+1, recipe)

        if response == '':
            response = ':disappointed: Sorry, no recipes found for your request. Please, try a new search'
        else:
            response = header + '\n' + response + '\n' + footer
        return response


    def suggest_dish(self):
        print('ingredients={0}, cuisine type={1}, intolerances={2}'.format(self.context['ingredients'],
                                                                           self.context['cuisine_type'],
                                                                           self.context['intolerances']))

        query = ''
        response = ':disappointed: Sorry, no recipes found for your request. Please, try a new search'

        if (self.context['suggest_dish']):
            if self.context['ingredients'] != None:
                query = query + self.context['ingredients']
            if self.context['cuisine_type'] != None:
                query = query + ' ' + self.context['cuisine_type']
            if self.context['intolerances'] != None:
                query = query + ' ' + self.context['intolerances']


            if query != '':
                print('Buscando receta para: << {} >>'.format(query))
                response = self.get_ingredients(self.get_recipe_id(query))

        return response


    def get_db_summary(self):
        all_products = []
        expired_products = []
        products_to_expire = []
        header = ''
        recap = ''

        # All products
        query_all = "SELECT name " \
                    "FROM products " \
                    "ORDER by name"
        all_products = self.fetch_content(query_all)

        # Expired products
        query_expired = "SELECT name " \
                        "FROM products " \
                        "WHERE date(expiration_date)<=current_date " \
                        "ORDER by name"
        expired_products = self.fetch_content(query_expired)

        # Products to expire in next DAYS_TO_EXPIRE days
        query_to_expire = "SELECT name " \
                          "FROM products " \
                          "WHERE date(expiration_date)>current_date " \
                          "AND date(expiration_date)<=current_date + interval '{} days' " \
                          "ORDER by name".format(DAYS_TO_EXPIRE)

        products_to_expire= self.fetch_content(query_to_expire)

        if len(all_products)>0:
            header = '\n\nThere are {0} products in total, ' \
                     '{1} products are already expired and {2} products will expire soon. '.\
                            format(len(all_products), len(expired_products), len(products_to_expire))

            if(len(expired_products)>0):
                footer = '\n\nThrow the expired foods out. '
                recap = recap + '\n\n' + ':recycle: *Already expired*:  {0}.'\
                    .format(', '.join(map(str, expired_products)))
            else:
                recap = recap + '\n\n' + 'Great! :clap: There are no expired products.'
            if(len(products_to_expire)>0):
                footer = footer + 'Consider using the foods to expire as soon as possible.'
                recap = recap + '\n\n' + ':alarm_clock: *To expire*:  {0}.'\
                    .format(', '.join(map(str, products_to_expire)))
            else:
                recap = recap + '\n\n' + 'Congrats! :v: There are no products to expire in the next {0} days.'\
                    .format(DAYS_TO_EXPIRE)

        else:
            recap= ':-1: You have the fridge EMPTY! :disappointed_relieved:' \
                    'Make the purchase if you do not want to starve. ' \
                    'Today you will have to order food at home.'

        return(header + recap + footer)


    def image_food_recognition(self):
        food, score = self.get_food_from_image('./download/food.jpg')
        if (food != 'non-food'):
            response = 'Uhm... :yum: :yum: :yum: This looks really good. I think (score: {1}) it is... *{0}*'\
                .format(food, score)
            self.send_response(response)
            response = '\n' + smartfridge.get_ingredients(self.get_recipe_id(food))
        else:
            response = 'Are you sure it is edible? I do not recognize food in this image. \nPlease, try with another one.'

        return response


    def get_recipe(self):
        recipe = ':disappointed: Sorry, no recipes found for your request. Please, try a new search'
        print('dish = {}'.format(self.context['dish']))
        print('search_recipe = {}'.format(self.context['search_recipe']))
        if (self.context['dish'] != None and self.context['search_recipe']):
            print('Buscando receta para: << {} >>'.format(self.context['dish']))
            recipe=self.get_ingredients(self.get_recipe_id(self.context['dish']))
        return recipe

    def get_ingredients(self, recipeId):
        print('recipe id = {}'.format(recipeId))
        response = ':disappointed: Sorry, no recipes found for your request. Please, try a new search'
        if recipeId != None:
            recipe = self.get_recipe_from_id(recipeId)
            if recipe and 'recipe' in recipe:
                ingredients=[]
                source = '\nHere, you can find the *method of cooking*: {}'.format(recipe['recipe']['source_url'])
                for ingredient in (recipe['recipe']['ingredients']):
                    ingredients.append(ingredient)
                    str_ingredients= '\nI found *{}*. To cook this you need the following *ingredients*:'\
                                         .format(recipe['recipe']['title']) + \
                                     '\n\n   - {}'.format('\n    - '.join(map(str, ingredients)))
                response = str_ingredients + '\n' + source

        return response



    def get_ingredients_information(self, ingredients):
        info = ""
        try:
            records = self.get_db_information_about_ingredients(ingredients)
            if len(records)>0:
                for r in records:
                    # Not expired product
                    if r[1].date() >= datetime.datetime.now().date():
                        info = info + '\n' + 'There are {0} grams of {1}, the expiration date is {2}'.\
                            format(round(r[2], 0), r[0], r[1].strftime("%d/%m/%Y"))
                    # Expired product
                    else:
                        info = info + '\n' + 'The {0} expired the day {1}. Throw it out!'\
                            .format(r[0], r[1].strftime("%d/%m/%Y"))
            else:
                info = 'There are no  {} left at home, write it down on the shopping list.'.format(ingredients)
        except:
            info = 'Sorry, we are having technical problems, please try again.'

        return info



    def get_top_rated_recipe(self):
        return self.get_ingredients(self.get_recipe_id(''))

    def get_trending_recipe(self):
        return self.get_ingredients(self.get_recipe_id('', 't'))

    def get_recipe_options_from_available_ingredients(self, n_options=2, n_ingredients=2):
        ingredients = []
        options = []

        # IMPROVEMENT: add to the query the register user intolerances
        ingredients = self.get_top_expired_ingredients_from_db(n_ingredients)

        if len(ingredients) > 0:
            query = ', '.join(map(str, ingredients))
            recipes = self.search_recipes(query)

        if recipes and 'recipes' in recipes:
            for recipe in recipes['recipes'][:n_options]:
                options.append(recipe['title'])
                self.option_dict[recipe['title']]=recipe['recipe_id']
        return options

    def update_conversation_context(self):
        print('update_conversation_context')
        return self.msg_to_conversation('')


    def msg_to_conversation(self, input_message):
        message = {}
        intent = ''
        entity = ''
        response_text = ''

        if (input_message != ''):
            message['text'] = input_message

        response = self.conversation.message(workspace_id=CONVERSATION_WORKSPACE,
                                             message_input=message,
                                             context=self.context,
                                             alternate_intents=False)

        self.update_local_context(response['context'])
        self.intents = response['intents']
        self.entities = response['entities']

        # Print intent and entity
        if (len(self.intents) > 0 and len(self.entities) > 0):
            print('#{0}  (@{1}:{2})'.format(self.intents[0]['intent'], self.entities[0]['entity'],
                                            self.entities[0]['value']))
            intent = self.intents[0]['intent']
            entity = self.entities[0]['entity']
        elif (len(self.intents) > 0):
            print('#{0}'.format(self.intents[0]['intent']))
            intent = self.intents[0]['intent']
        elif (len(self.entities) > 0):
            print('@{0}:{1}'.format(self.entities[0]['entity'], self.entities[0]['value']))
            entity = self.entities[0]['entity']

        if (response["output"] and response["output"]["text"]):
            for r in response["output"]["text"]:
                response_text = response_text + '\n' + r

        return response_text, intent, entity

    def update_local_context(self, context):
        self.context = context
        for key, value in self.context.items():
            print('{0} = {1}'.format(key, value))
        print('\n')



    ######   VISUAL RECOGNITION ########
    def get_food_from_image(self, image_path):
        with open(image_path, 'rb') as image_file:
            vr_response = self.visual_recognition.classify(images_file=image_file, classifier_ids=['food'])
            if vr_response['images'] and len(vr_response['images']) > 0:
                image = vr_response['images'][0]
                if image['classifiers'] and len(image['classifiers']) > 0:
                    classifier = image['classifiers'][0]
                    if classifier['classes'] and len(classifier['classes']) > 0:
                        food = classifier['classes'][0]['class']
                        score = classifier['classes'][0]['score']
                        return food, score
        return None, None



    ######   SLACK ########
    """
        The Slack Real Time Messaging API is an events firehose.
        this parsing function returns None unless a message is
        directed at the Bot, based on its ID.
    """
    def parse_slack_output(self, slack_rtm_output, download_path='download/food.jpg'):
        output_list = slack_rtm_output
        if output_list and len(output_list) > 0:
            for output in output_list:
                if output and 'text' in output and AT_BOT in output['text']:
                    # return text after the @ mention, whitespace removed
                    return output['text'].split(AT_BOT)[1].strip().lower(), output['channel']
                elif output and 'file' in output and 'url_private_download' in output['file']:
                    down_url = output['file']['url_private_download']
                    extension = os.path.splitext(down_url)[1][1:].strip().lower()
                    if extension in ['jpg', 'png']:
                        self.download_file(down_url, download_path, 'download')
                        return 'photo', output['channel']
                    else:
                        return 'download_file_format_error', output['channel']
        return None, None

    # Provide response
    def send_response(self, response):
        result = self.slack_client.api_call("chat.postMessage",
                                            channel=channel,
                                            text=response,
                                            as_user=True)
        return result


    def download_file(self, url, local_filename, basedir):
        try:
            os.stat(basedir)
        except:
            os.mkdir(basedir)
        try:
            print('Savigng to {}'.format(local_filename))
            headers = {'Authorization': 'Bearer '+ os.environ.get('SLACK_BOT_TOKEN')}
            r = requests.get(url, headers=headers)
            with open(local_filename, 'wb') as f:
                for chunk in r.iter_content(chunk_size=1024):
                    if chunk:
                        f.write(chunk)
        except:
            return False

        return True



    #######   FOOD2FORK    #######
    def food2fork_request(self, endpoint, **kwargs):
        data = {'key': FOOD2FORK_KEY}
        for key, value in kwargs.items():
            data[key] = value
        return endpoint + '?' + urllib.parse.urlencode(data)


    def search_recipes(self, query, sortBy='r'):
        endpoint = 'http://food2fork.com/api/search'
        url = self.food2fork_request(endpoint, q=query, sort=sortBy)
        print(url)
        return requests.get(url).json()


    def get_recipe_from_id(self, recipeId):
        endpoint = 'http://food2fork.com/api/get'
        try:
            url = self.food2fork_request(endpoint, rId=recipeId)
            print(url)
            return requests.get(url).json()
        except Exception as inst:
            print(inst)
            return None


    def get_recipe_id(self, query, sortBy='r'):
        recipes=self.search_recipes(query, sortBy)
        if recipes and 'recipes' in recipes and len(recipes['recipes'])>0:
            return(recipes['recipes'][0]['recipe_id'])
        else:
            return None



    def get_top_rated_recipe_options(self, n_options=1):
        options = []
        recipes = self.search_recipes('')
        if recipes and 'recipes' in recipes:
            for recipe in recipes['recipes'][:n_options]:
                options.append(recipe['title'])
                self.option_dict[recipe['title']] = recipe['recipe_id']
        return options



    def get_trending_recipe_options(self, n_options=1):
        options = []
        recipes = self.search_recipes('', sortBy='t')

        if recipes and 'recipes' in recipes:
            for recipe in recipes['recipes'][:n_options]:
                options.append(recipe['title'])
                self.option_dict[recipe['title']] = recipe['recipe_id']

        return options





    ######   POSTGRES DATABASE ########

    def database_connection(self, str_db_connection):
        print('Connecting to database ... ')
        # get a connection, if a connect cannot be made an exception will be raised here
        db_conn = psycopg2.connect(str_db_connection)
        # conn.cursor will return a cursor object, you can use this cursor to perform queries
        self.database_cursor = db_conn.cursor()


    def fetch_content(self, query):
        # execute Query
        self.database_cursor.execute(query)

        # retrieve the records from the database
        records = self.database_cursor.fetchall()
        record_list=[]
        for r in records:
            record_list.append(r[0])
        return(record_list)


    # Obtain the n_ingredients products with the closest expiration date and that are in more quantity
    def get_top_expired_ingredients_from_db(self, n_ingredients=2):
        ingredients = []
        db_query = 'SELECT name ' \
                    'FROM products ' \
                    'WHERE date(expiration_date) > current_date ' \
                    'ORDER by expiration_date ASC, quantity DESC ' \
                    'LIMIT {}'.format(n_ingredients)

        ingredients = self.fetch_content(db_query)

        return ingredients

    def get_db_information_about_ingredients(self, ingredients):
        query = "SELECT name, expiration_date, quantity " \
                "FROM products " \
                "WHERE name like '%{}%'".format(ingredients)

        self.database_cursor.execute(query)
        records = self.database_cursor.fetchall()

        return records
예제 #9
0
class CustomClassifier():

    def __init__(self):
        self.visual_recognition = VisualRecognition('2016-05-20', api_key=config.api_key)
        self.downloader = ImageDownloader(config.yoox_rest_endpoint)

    """
    This method creates a new visual custom classifier starting from a file path.
    The path will be a directory containing a group of zip files filled with jpg images, each file represents a class sample data
    @type classifierName: string
    @param classifierName: new custom classifier name
    @type inputDataPath: string
    @param inputDataPath: zip files directory path
    """
    def create_custom_classifier(self, classifierName, inputDataPath): # it could take a negative examples data path as input
        params = {}
        for dirname, subdirs, files in os.walk(inputDataPath):
            for file in files:
                absname = os.path.abspath(os.path.join(dirname, file))
                name = os.path.splitext(os.path.basename(file))[0]
                params[name.replace("-", "_") + "_positive_examples"] = open(absname)
        if config.print_file_params_long_object:
            print params

        # for dirname, subdirs, files in os.walk(negDataPath):
        #     for file in files:
        #         absname = os.path.abspath(os.path.join(dirname, file))
        #         name = os.path.splitext(os.path.basename(file))[0]
        #         params["negative_examples"] = open(absname)

        print "Uploading files to Visual Recognition servers... It will take several time based on the number of images"
        response = self.visual_recognition.create_classifier(classifierName, **params)
        print "Watson classifier created: ", json.dumps(response)
        self.classifier_id = response['classifier_id']

    def sameIdCondition(self, id, inputID):
        return id == inputID

    """
    This method retrieves a classifier by id
    @type classifier_id: string
    @param classifier_id: classifier id
    @return response: Watson's representation of a classifier
    """
    def getClassifiers(self, classifier_id):
        response = self.visual_recognition.get_classifier(classifier_id=classifier_id)
        return response

    """
    This method retrieves this classifier representation
    @return response: Watson's representation of a classifier
    """
    def getClassifierStatus(self):
        return self.getClassifiers(self.classifier_id)

    """
    This method recharge a Watson visual recognition classifier by id
    @type classifier_id: string
    @param classifier_id: classifier id
    """
    def recharge_classifier(self, classifier_id):
        # if the classifier does not exist it will fail
        self.classifier_id = self.getClassifiers(classifier_id)['classifier_id']

    """
    This method requests to the classifier for an image classification starting from an image ID of the csv file
    @type imageId: string
    @param imageId: an image ID contained in the csv training set file
    @return: the visual recognition representation of the requested image classification
    """
    def classify_image_fromTrainingSet(self, imageId, threshold):
        # Read the CSV File
        allImages = pre_processing.readingFromInputFile(config.csv_path)
        # in a production env it should be necessary to handle the not found exception
        imgEl = [el for el in allImages if imageId == el.id][0]
        print config.temp_data_path
        if not os.path.isdir(config.temp_data_path):
            os.makedirs(config.temp_data_path)
        # Download the image
        imgPath = self.downloader.downloadAndSaveImage(config.temp_data_path, imgEl)
        print "Sending classification request to classifier"
        return self.visual_recognition.classify(open(imgPath), classifier_ids=[self.classifier_id], threshold=threshold)

    """
    This method requests to the classifier for an image classification starting from its ID
    @type imageId: string
    @param imageId: an image ID contained in the csv training set file
    @return: the visual recognition representation of the requested image classification
    """
    def classify_image(self, imageId, threshold):
        imgPath = self.downloader.downloadAndSaveImage(config.temp_data_path, InputImgElement(imageId))
        print "Sending classification request to classifier"
        return self.visual_recognition.classify(open(imgPath), classifier_ids=[self.classifier_id], threshold=threshold)