# Error in sepia effect opencv python

I'm trying to create a filter which will create a sepia look for all pictures. But I get some spots in my filtered image which are blue and cyan. I think it might be overflow but I tried to account for that and it didnt give me the affect I was looking for. I'm not sure whats wrong. The link to original is at https://www.dropbox.com/s/pd0esc8tef3smae/Lampard.jpg and after the modification, it becomes https://www.dropbox.com/s/f9n9lrhoi1qqs53/Lampard_blue.jpg

def filter3(path, cv2): cv2.destroyAllWindows() cv2.namedWindow("Filter 3") img = cv2.imread(path, cv2.IMREAD_UNCHANGED) newImg = img (i,j,k) = img.shape for x in xrange(i): for y in xrange(j): b = img[x,y,0] g = img[x,y,1] r = img[x,y,2] if(k == 4): newImg[x,y,0] = np.uint16(b * 0.272 + g * 0.534 + r * 0.131) newImg[x,y,1] = np.uint8(b * .349 + g * 0.686 + r * 0.168) newImg[x,y,2] = np.uint8(b * 0.393 + g * 0.769 + r * 0.189) # newB = np.uint16(b * 0.272 + g * 0.534 + r * 0.131) # newG = np.uint16(b * .349 + g * 0.686 + r * 0.168) # newR = np.uint16(b * 0.393 + g * 0.769 + r * 0.189) # if(newB > 255): # newImg[x,y,0] = np.uint8(255) # else: # newImg[x,y,0] = np.uint8(newB) # if(newG > 255): # newImg[x,y,1] = np.uint8(255) # else: # newImg[x,y,1] = np.uint8(newB) # if(newR > 255): # newImg[x,y,2] = np.uint8(255) # else: # newImg[x,y,2] = np.uint8(newB) newImg[x,y,3] = img[x,y,3] else: newImg[x,y,0] = np.uint16(b * 0.272 + g * 0.534 + r * 0.131) newImg[x,y,1] = np.uint8(b * .349 + g * 0.686 + r * 0.168) newImg[x,y,2] = np.uint8(b * 0.393 + g * 0.769 + r * 0.189) # if(newB > 255): # newImg[x,y,0] = np.uint8(0) # else: # newImg[x,y,0] = np.uint8(newB) cv2.imshow("Filter 3", newImg) return newImg

## Answers

I don't know python but you can refer below C++ code works fine for me.

Mat src=imread("Lampard.jpg",1); Mat SepiaKernel = (Mat_<float>(4,4) << 0.189, 0.769, 0.393, 0,\ 0.168, 0.686, 0.349, 0,\ 0.131, 0.534, 0.272, 0,\ 0.000, 0.000, 0.000, 1); Mat dst; transform(src, dst, SepiaKernel); imshow("src",src); imshow("sepia",dst); waitKey();

**Result:-**

In my opinion problem is with types. Python thinks that after operation you want to integer. Each channel has 8 bits. After calculation when you will get value 256 (100000001) python will read only first 8 bits (00000001). Because of that you have a little bit strange image. In my case works this code:

import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('lena.jpg') newImage = cv2.imread('lena.jpg') i, j, k = img.shape for x in xrange(i): for y in xrange(j): R = img[x,y,2] * 0.393 + img[x,y,1] * 0.769 + img[x,y,0] * 0.189 G = img[x,y,2] * 0.349 + img[x,y,1] * 0.686 + img[x,y,0] * 0.168 B = img[x,y,2] * 0.272 + img[x,y,1] * 0.534 + img[x,y,0] * 0.131 if R > 255: newImage[x,y,2] = 255 else: newImage[x,y,2] = R if G > 255: newImage[x,y,1] = 255 else: newImage[x,y,1] = G if B > 255: newImage[x,y,0] = 255 else: newImage[x,y,0] = B cv2.imshow('image',newImage) cv2.waitKey(0) cv2.destroyAllWindows()

Maybe it's not nice code, but I'm not familiar with Python.