Visual Cryptography and Bit-Plane Complexity Segmentation

The Implementation

To illustrate this model, I wrote an application using Python, the Python Imaging Library (PIL) (www.pythonware.com/products/pil/), and the numarray package for Python (www.stsci.edu/resources/software_hardware/numarray). PIL adds image-processing capabilities to Python and processes a range of image formats. numarray lets Python efficiently manipulate large numeric arrays, similar to Matlab, IDL, or Octave.

There is a common convention in processing binary (black-and-white) images: If any black pixel in the image is denoted by 1 and any white pixel is 0, you can "transform" any binary black-and-white image into a binary matrix. This is the approach used in my application.

In the embedding process, you select 858 squares from a larger matrix (a share in the model) and write back 9x9 squares into some other matrix (normally a bit-plane); see Listings One and Two, respectively. The algorithm to calculate the complexity of a region in a bit-plane can be implemented as in Listing Three.

```def square(matrix, n, d):
# returns a square slice of dim d from a matrix
# n - square number
maxX = len(matrix[0])
maxY = len(matrix[:,0])
xsquares = maxX/d
ysquares = maxY/d
dy, dx = divmod(n, xsquares)
xslc = dx * d
yslc = dy * d
return matrix[xslc:xslc+d, yslc:yslc+d]```
Listing One

```def writesquare(matrix, square, n):
# writes a square of dim d into a bigger matrix
# n - square number
# returns the matrix with the overwritten sqaure
maxX = len(matrix[0])
maxY = len(matrix[:,0])
sqX = len(square[0])
sqY = len(square[:,0])
xsquares = maxX/sqX
ysquares = maxY/sqY
dy, dx = divmod(n, xsquares)
xslc = dx * sqX
yslc = dy * sqY
matrix[xslc:xslc+sqX, yslc:yslc+sqY] = square
return matrix```
Listing Two

```def complexity(matrix):
maxX = len(matrix[0])
maxY = len(matrix[:,0])
norm = maxX*maxY
cmp = 0.
first = matrix[0][0]
for x in range(maxX):
for y in range(maxY):
if first != matrix[x][y]:
cmp += 1
first = matrix[x][y]
if cmp != 0:
cmp /= norm

return cmp```
Listing Three

To ensure the "blind" character of the embedding scheme, you have to provide additional information (like sequence number and the flag for the conjugated areas) to any 8x8 square read from a share. The additional information is written back into the vessel, together with the 8x8 square of embedding data. The required space is obtained by bordering the square with one row and one column. Though generally defined, the functions in Listings Four(a) and (b) can perform the bordering as well.

```(a)
def insert_line(where, line, matrix):
maxX = len(matrix[0])
maxY = len(matrix[:,0])+1
if len(line) != maxX:
print "[ERR] Unable to append line."
sys.exit(1)
getback = zeros((maxY, maxX))
for y in range(maxY):
if y == where:
getback[y] = line
else:
if y < where:
getback[y] = matrix[y]
else:
getback[y] = matrix[y-1]
return getback

(b)
def insert_column(where, column, matrix):
tmatrix = transpose(matrix)
tcolumn = transpose(column)
tmpback = insert_line(where, tcolumn[0], tmatrix)
return transpose(tmpback)```
Listing Four

The program also provides other tools for tasks such as generating a random binary matrix or checkerboard pattern, initializing log files, defining some standard directories, and the like. All these are implemented in a utils package.

The application has compression, embedding, and extraction modules. All components work on 8-bit gray-level or 24-bit true-color images. I focus on the 8-bit images because the processing of the true-color images only involves this extension: PIL lets you switch between different pixel representations of an image using the convert function. In terms of converted images, there are only two accepted formats: L (8-bit grayscale) and/or RGB (24-bit true color). This lets you convert input images in RGB format like this:

```
try:
image = __original_image.convert("RGB")
except IOError:
print "Cannot convert image: "      + image_name

```

After a successful conversion, the image object is in RGB format. For such objects, PIL offers a method that returns a tuple containing the individual image components ("bands" in the PIL documentation). This means you can say:

```
red, green, blue = image.split()

```

The red, green, blue objects this time are 8-bit grayscale images. All three modules of the application are implemented in a separate class called image.

Compression, which is based on BPCS, only determines image regions with a complexity above a determined threshold. These regions are overwritten with white color. The embedding module uses the modified BPCS scheme. The module performs the bordering of the 8x8 initial square, correspondingly inserting the sequence numbers and the "conjugated flag" if needed (see Listing Six, available at www.ddj.com/code/).

The function starts with a given sequence number and returns the last sequence number it used. This is because of the embedding scenario itself: During the process, you have to move from one bit-plane to another, and, in the case of true-color images, from one color component to another. So the function has to "know" what the current sequence number is and return the sequence number it finished with for the next iteration.

The extraction module checks the complexity of any region in the image and searches for embedded data. The application also tries to determine if the complete chain of sequence numbers was extracted; if not, it reports the missing squares.

As in Table 1, the only 2x2 matrices that should exist in a share are the diagonal ones. The extraction module also uses an error-detecting mechanism and informs you if some region of the image was altered—a "wrong" 2x2 matrix was found. As the embedding function, the extraction function starts with an initial sequence number and returns the next sequence number when finished (see Listing Seven, available at www.ddj.com/code/).

More Insights

 To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.

First C Compiler Now on Github

The earliest known C compiler by the legendary Dennis Ritchie has been published on the repository.

HTML5 Mobile Development: Seven Good Ideas (and Three Bad Ones)

HTML5 Mobile Development: Seven Good Ideas (and Three Bad Ones)

Building Bare Metal ARM Systems with GNU

All you need to know to get up and running... and programming on ARM

Amazon's Vogels Challenges IT: Rethink App Dev

Amazon Web Services CTO says promised land of cloud computing requires a new generation of applications that follow different principles.

How to Select a PaaS Partner

Eventually, the vast majority of Web applications will run on a platform-as-a-service, or PaaS, vendor's infrastructure. To help sort out the options, we sent out a matrix with more than 70 decision points to a variety of PaaS providers.