Errata

Programming Computer Vision with Python

Errata for Programming Computer Vision with Python

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Printed Page p181
Line 6 from bottom

My compter environment: Windows 7, python 2.7, libsvm-3.16
I didn't know whether python 3 or a different verion libsvm will produce the same problem.
---------------------------------------------------------------------------------------
When run this code on page 181, libSVM will produce an error, said
TypeError: [can only concatenate list (not "tuple") to list]
at the sentence
xi = [0] + xi
in libsvm function gen_svm_nodearray()
The above sentence requires xi at the right hand should also be a list.
However, the zip(x,y) at line 6 from bottom on page 181 will create
a list of TUPLE, not a list of LIST. This is the reason for the error.

This problem can be solved just as defining function "predict" as
follow:

def predict(x,y,model=m):
dsample =[]
for i in range(len(x)):
dsample = dsample + [[x[i],y[i]]]
return array(svm_predict([0]*len(x),dsample,model)[0])

P.S.
Just as the same as Mr. aikawa pointed out, the [-1,1] should be
[1,-1] at the line 4 from bottom.

ColorRGB  Feb 25, 2013 
Printed Page p181
Line 6 from bottom

My compter environment: Windows 7, python 2.7, libsvm-3.16
I didn't know whether python 3 or a different verion libsvm will produce the same problem.
---------------------------------------------------------------------------------------
When run this code on page 181, libSVM will produce an error, said
TypeError: [can only concatenate list (not "tuple") to list]
at the sentence
xi = [0] + xi
in libsvm function gen_svm_nodearray()
The above sentence requires xi at the right hand should also be a list.
However, the zip(x,y) at line 6 from bottom on page 181 will create
a list of TUPLE, not a list of LIST. This is the reason for the error.

This problem can be solved just as defining function "predict" as
follow:

def predict(x,y,model=m):
dsample =[]
for i in range(len(x)):
dsample = dsample + [[x[i],y[i]]]
return array(svm_predict([0]*len(x),dsample,model)[0])

P.S.
Just as the same as Mr. aikawa pointed out, the [-1,1] should be
[1,-1] at the line 4 from bottom.

ColorRGB  Feb 25, 2013 
PDF, ePub, Page Chapter 1
Section 1.1

Text throughout the title refers to the Python Imaging Library (PIL) at https://www.pythonware.com.

It appears pythonware.com is an invalid domain. The same link appears in the Wikipedia article, so it doesn't seem like a typo, but rather a broken domain.

DSchneider  May 25, 2022 
Printed Page 13
Line 3 from bottom

In the 'else' section of the function pca(),

1. The number of rows is definitely greater than the number of columns(dimension), that is, num_data >= dim
2. After computed the SVD, the matrix V is dim x dim
3. V[:num_data] is the same with the original V

Conclusion: It is no need for the sentence V=V[:num_data]

Isn't right?

ColorRGB  May 05, 2013 
Printed Page 19,20,22
Figure 1-10, 1-11, 1-12

The images of gradient magnitude are inverted in Figure 1-10 (d) and Figure 1-11 (bottom).

Figure 1-12 seems inverted, too.

aikawa  Feb 23, 2013 
Printed Page 30
4th paragraph

The quotient det(M)/trace(M)^2 is not correct.
According to [Noble 1989], the corner measure is
2 det(M) / {trace(M)+e}.

The original code below is correct rather than the author's fix on Jan 23, 2013.

aikawa  Feb 17, 2013 
Printed Page 30
4

In the discussion of the Harris operator the quotient contains the square of the trace. I don't think this is right: according to Brown, Szeliski & WInder (2005) it should be without the square. I tried det(M)/trace(M), which worked well, and det(m)/(trace(m)**2), which gave very poor discrimination (no strong corner points).

Anonymous  Sep 03, 2013 
Printed Page 39
Source code of plot_features() function

In the comment, the sentence

locs (row, col, scale, ...)

should be

locs (col, row, scale, ...)

since the format of each line of sift output file (on page 38) is

x y scale orientation ...

ColorRGB  May 11, 2013 
PDF Page 40
source code block, function 'match'

'matchscores' variable is initialized to zeros. But 0 being a valid index value, I guess it should be initialized to - ones, if my understanding is correct. If my point is valid, it should trigger changes in the function 'match_twosided' in page 41 where a value of 0 for indices should be accepted in the statement 'ndx_12 = matches_12.nonzero()[0]'.

Anonymous  Jan 06, 2013 
Printed Page 63
code

alpha = alpha_for_triangle(tp[:,t],im.shape[0],im.shape[1])

will cause an error in alpha_for_triangle() because the arguments for range() are not integer.
This should be:

alpha = alpha_for_triangle(tp[:,t].astype('int'),im.shape[0],im.shape[1])

aikawa  Feb 17, 2013 
Printed Page 68
Line 7 from top

The code says offset = [-ty,-tx]
since tx, ty are computed from refpoints to points, when backward (reverse) mapping, I think the offset should be
dot(linalg.inv(T), [-ty, -tx])
something like that.

ColorRGB  Feb 20, 2013 
Printed Page 72
code

The SIFT program gives the location coordinates in [x,y] order, but ndimage uses the [row,col] order.
The coordinates should be swapped as:

for i in range(5):
sift.process_image(imname[i],featname[i])
l[i],d[i] = sift.read_features_from_file(featname[i])
l[i][:,[0,1]] = l[i][:,[1,0]] # x,y -> row,col

aikawa  Feb 23, 2013 
Printed Page 73
code on normalizing hom. coordinates

Divided by Zero error causes at:
for i in range(3):
fp_transformed[i] /= fp_transformed[2]

This can be avoided by modifying like:

nz = nonzero(fp_transformed[2])
for i in range(3):
fp_transformed[i][nz] /= fp_transformed[2][nz]

aikawa  Feb 23, 2013 
Printed Page 74
argument in H_from_ransac()

def H_from_ransac(fp,tp,...,match_theshold=10):
should be:
def H_from_ransac(fp,tp,...,match_threshold=10):

aikawa  Feb 23, 2013 
Printed Page 76
code to make alpha values of a color image.

The alpha value calculated by:
alpha = ((fromim_t[:,:,0] * fromim_t[:,:,1] * fromim_t[:,:,2] ) > 0)

will be zero if some component of RGB is zero, so that pure red (255,0,0) pixels, for example, will be regarded as transparent.

This should be:
alpha = ((fromim_t[:,:,0] + fromim_t[:,:,1] + fromim_t[:,:,2]) > 0)

aikawa  Feb 23, 2013 
Printed Page 96
code

The code on P.96 will not show the image like Figure 4-6, because the vertex values are too big, and Y and Z axes are not swapped in toyplane.obj downloaded from http://www.oyonale.com/.

obj = objloader.OBJ(filename,swapyz=True)
glCallList(obj.gl_list)

should be:

glEnable(GL_NORMALIZE)
glScalef(0.0085,0.0085,0.0085)
obj = objloader.OBJ(filename,swapyz=False)
glCallList(obj.gl_list)

aikawa  Feb 22, 2013 
Printed Page 129
2nd line

The file 'a_pca_modes.pkl' should be 'font_pca_modes.pkl' saved on P.15.

aikawa  Feb 23, 2013 
Printed Page 131
after 'scaled' computation

Running this code will cause a Typeerror which says 'integer argument expected, got float'. The reason is that the paste() function requires box to be integer. However,
(scaled[i][0]-ns[0]//2, scaled[i][1]-ns[1]//2,
scaled[i][0]+ns[0]//2+1,scaled[i][1]+ns[1]//2+1)
gives a float tuple, since 'scaled' is a float array.

The problem can be solved by adding the following sentence after computed 'scaled':
scaled = scaled.astype(int)

ColorRGB  Mar 03, 2013 
Printed Page 133
Figure 6-4

The caption of Figure 6-4 and the code on P.132 say k=3, but the image implies k=2.

aikawa  Feb 23, 2013 
Printed Page 143
code

(1)
im = Image.open(path+imlist[ind[i]])

'path' is undefined in the code nor the text before.
It will be unnecessary because imlist contains the path to the files.

(2) gray() is necessary for each imshow()


aikawa  Feb 23, 2013 
Printed Page 150
1st paragraph

Clarification to using the imlist as the list containing the filenames of images.
If imlist is obtained from a simple directory glob (e.g. imlist = glob.glob(r'/home/computer_vision/ukbench/*.jpg'),
then imlist must be sorted in order for this part of the vocabulary to work properly.

When continuing on page 158, the ordering of imlist must correspond properly with the database index or else you would a erroneous accuracy report.

Therefore, running imlist.sort() will solve the problem.

Tom  Mar 01, 2014 
Printed Page 156,157
code

src = imagesearch.Searcher('test.db')

should be

src = imagesearch.Searcher('test.db', voc)

aikawa  Feb 23, 2013 
Printed Page 161
6th line

locs,descr = sift.read_features_from_file(featlist[ndx])

must be

locs,descr = sift.read_features_from_file(featlist[ndx-1])

because 'ndx' is a rowid of the DB that starts at 1.

aikawa  Feb 23, 2013 
Printed Page 163
code

The file 'webimlist.txt' loaded in __ini__() is not described anywhere.

The DB file 'web.db' loaded in index() is not described anywhere.

aikawa  Feb 23, 2013 
Printed Page 164
service.conf example

In service.conf for Cherrypy, tools.staticdir.root must be an absolute path.

Setting "tmp/" will cause an error.

aikawa  Feb 23, 2013 
Printed, PDF Page 167-190
Chapter 8

There are no source files for chapter 8 on GIT for download, I pieced together the Sodoku based on the PDF but there are still errors in the printed source or I'm missing some library I have to import.

Would it be possible to get working sourcecode files for chapter 8 please (specifically the sodoku character recocnition example)?

Best regards

Ulrich Hartmann

Ulrich Hartmann  Dec 30, 2013 
Printed Page 168
The last line in function classify

return max(votes) will return the larger key.
for example, if votes = {1:1, -1:2} for kNN, the code return 1. However, what we expected is -1.

This problem can solved by
return max(votes, key=lambda x: votes.get(x))

ColorRGB  Feb 20, 2013 
Printed Page 177
Line 5 from top

For N sample data with d dimensions, the dot operation
dot(x, dot(S,x.T))
will produce a N x N array.
If N is very large,

y = exp(-0.5*diag(dot(x,dot(S,x.T)))

will cause a memory error.
In fact in my computer environment (Windows 7, memory 2.00GB), the code in the book produced a memory error. I think somebody will be the same.

Since only the diagonal is needed, compute every elements in the array is not required.
The possibility of memory error can be reduced by replace sentence

y = exp(-0.5*diag(dot(x,dot(S,x.T)))

by following code

y = zeros((n,1))
for i in range(n):
for j in range(d):
y[i] += 1.0/v[j]*x[i,j]*x[i,j]
y[i] = exp(-0.5*y[i])

Somebody can write a more compact code.

Over.

ColorRGB  Feb 25, 2013 
Printed Page 177

Sorry, in the [Unconfirmed Errata by ColorRGB Feb 25, 2013]
y = zeros((n,1))
should be
y = zeros(n)

If use y = zeros((n,1)), function
print_confusion(res, test_labels,classnames)
in page 179 will cause an error.

ColorRGB  Feb 25, 2013 
Printed Page 181,182
code and FIgure 8-5

In Figure 8-5, the correctly classified points are shown with circles, not with stars as written in the caption and Figure 8-1, 8-4.

The code on P.181:
imtools.plot_2D_boundary( ... , [-1,1])
should be
imtools.plot_2D_boundary( ... , [1,-1])

aikawa  Feb 22, 2013 
Printed Page 188
At the end of the code

When running this code on the MSDOS command prompt, there is no problem. However, running it in IDLE(Python GUI) or PyScripter, the shown window can not terminated.
This problem can be solved by adding the following command at the end of the code:
show()

ColorRGB  Feb 28, 2013 
Printed Page 197,199,and so on
text and caption

"Grab Cut" should be "GrabCut".

aikawa  Feb 23, 2013 
Printed Page 212
At the bottom of the page

When reading an image, the default channel order is BGR, the function pyrDown does not change the channel order. The flag in function cvtColor should be BGR2GRAY, not RGB2GRAY.

Changing RGB2GRAY to BGR2GRAY, the SURF features are also changed in Figure 10-3.

ColorRGB  Feb 28, 2013 
PDF Page 244
Figure 9.2

Hy,

I'm trying to learn about graph-cut image segmentation, and I've found in your book a nice example for this problem. I've tried to reproduce your solution in your book, which is free available, and the name is:
ProgrammingComputerVision_CCdraft.pdf
and the website which I've downloaded from was called:
http://programmingcomputervision.com/

I've run your code graphcut.py, and bayes.py successfully, and the example as well, with the empire.jpg image.
But the result picture in your book (page 244, Figure 9.2 ) is not the same as the one what I had run on my computer. My pictures contains too much background, the tower's border doesn't come out so nice, and clearly as in your code.

I don't know what can be the problem. The solution in your book is too far away from my solution what I had run on my computer.
Did you change something in your source code after you had written it in your book?
I've tried as a solution to convert the picture to grayscale if it could help, but it didn't help:
im = array(Image.open(’empire.jpg’).convert('L'))
im = imresize(im,0.07,interp=’bilinear’)

and that was necessary to change the image vector in the graphcut.py code:
vim = im.reshape((-1,1))
# RGB for foreground and background
foreground = im[labels==1].reshape((-1,1))
background = im[labels==-1].reshape((-1,1))
Here I changed the 3 to 1 channel, but as I said it didn't help.

Thank you

Anonymous  Jun 05, 2015