• No results found

Implementation

4 Image Tagger: a web-based prototype for tagging images

4.3 Implementation

The first implementation stage was to create the database structure to store the tags and other tag-related data from the sessions with the participants. The following Structural Semantic

25 http://www.prototypejs.org/

Model (SSM), described by Nordbotten (2008), shows how the relational database was set up.

The data types shown after the attribute names follow the MySQL-specification.

Figure 14: SSM-model showing the relational structure of Image Tagger’s underlying database.

Hopefully, the model is relatively self-explanatory26 – but some comments are nevertheless provided here. Starting from left, the Sequence attribute of the TAGS relation is the sequence of which a tag is applied by a person. For instance, if a person chose the tag ‘man’ as the third tag for a certain image, the sequence number for that tag would then be 3. The Start_time and Stop_time attributes in the relation SPENDS_TIME_ON between the entities PERSON and IMAGE, are timestamps taken when a user starts to tag an image and when he or she is done with that. This data can be used to establish how much time each participant spent on tagging each image.

Based on the model shown in Figure 14, the following SQL CREATE-statements was specified and executed:

26 Basic knowledge of database modeling is assumed.

CREATE DATABASE `image_database`;

CREATE TABLE `image_database`.`image` ( `image_id` int(10) NOT NULL auto_increment, `image` mediumblob NOT NULL,

PRIMARY KEY (`image_id`) ) ENGINE=InnoDB;

CREATE TABLE `image_database`.`person` ( `person_id` int(10) NOT NULL auto_increment, `sex` tinyint(1) NOT NULL,

`age` int(10) NOT NULL, `experience` int(10) NOT NULL, `comment` text,

PRIMARY KEY (`person_id`) ) ENGINE=InnoDB;

CREATE TABLE `image_database`.`tags` ( `tags_person_id` int(10) NOT NULL, `tags_image_id` int(10) NOT NULL, `string` varchar(255) NOT NULL, `sequence` int(10) NOT NULL,

PRIMARY KEY (`tags_person_id`,`tags_image_id`,`string`), KEY `FK_tags_2` (`tags_image_id`),

CONSTRAINT `FK_tags_1` FOREIGN KEY (`tags_person_id`) REFERENCES `person` (`person_id`), CONSTRAINT `FK_tags_2` FOREIGN KEY (`tags_image_id`) REFERENCES `image` (`image_id`) ) ENGINE=InnoDB;

CREATE TABLE `image_database`.`time_spent` ( `person_id` int(10) NOT NULL,

`image_id` int(10) NOT NULL, `start_time` datetime NOT NULL, `stop_time` datetime NOT NULL,

PRIMARY KEY (`person_id`,`image_id`), KEY `FK_time_spent_2` (`image_id`),

CONSTRAINT `FK_time_spent_1` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`), CONSTRAINT `FK_time_spent_2` FOREIGN KEY (`image_id`) REFERENCES `image` (`image_id`) ) ENGINE=InnoDB;

Figure 15: The SQL CREATE-statements for the Image Tagger database.

After creating the database and its four tables, the database was populated with the 20 images from ULB. The second stage of the implementation process was to design the graphical user interface of the Image Tagger. This was done by creating a mockup with pen and paper. The mockup was revised several times during the process. The third and final stage of the implementation process was to code the application using the programming tools and languages described in section 4.2. This was an iterative process. The Image Tagger underwent several changes during the development process as a result of testing and user feedback.

The Image Tagger source code (except CSS) can be found in appendix G. The code is distributed among seven PHP-files, which in turn includes PHP-code, PHP/HTML-code or PHP/HTML/JavaScript code. To comment on all the code is beyond the scope of this thesis.

However, an example of an important function is provided here:

As mentioned in section 4.1, an essential matter was that for each user, the sequence in which the images appeared was randomized. The function that makes this possible was implemented the following way: First, the PHP-function getForPersonUntaggedImageID was written to allow retrieval of a random image ID for an image a person has not yet tagged. The function takes one argument; the ID of the person in question:

function getForPersonUntaggedImageID($person_id) {

$query = "

select image_id from image where image_id not in (

select distinct tags_image_id from tags where tags_person_id='$person_id'

)

order by rand() limit 1

";

$result = mysql_query($query) or die(mysql_error());

return mysql_numrows($result) == 0 ? 0 : mysql_result($result, 0);

}

Figure 16: Screenshot showing an example from the Image Tagger source code.

The query is first stored in a variable, namely $query. The inner SELECT-statement retrieves all the image-IDs of the images the user in question has tagged from the table tags. The outer SELECT-statement then retrieves all the image-IDs from the table image that are not among those. This gives a table of image-IDs for images the person in question has not yet tagged.

The order of this table is then randomized using the statement order by rand(). Finally, only the first ID of the first row is selected, using limit 1.

The query is sent to the MySQL-database using the function mysql_query, which takes a SQL query as parameter – in this case, the variable $query. The result of the query is stored in the variable $result as a resource, which is a special PHP-variable, holding a reference to an external resource.

The last line of code is a conditional expression equivalent to an IF-ELSE-statement – expressed using the ternary operator. It is this line that determines what the function getForPersonUntaggedImageID actually returns. First, the function mysql_numrows provides the number of rows in the result set stored in the variable $result. If this number equals 0 – i.e. that there are no images left that the person in question has not yet tagged – the function returns 0. If, on the other hand, there are images that the person has not yet tagged, this number equals 1. In that case, the function returns the value of the only cell in the row, which is a random image ID for an image the person in question has not tagged.