SciTech-BigDataAI-ImageProcessing-Numerical Analysis-Useful Operations-Color Image Channels with OpenCV+NumPy+Pandas

Links:

Shortpath Codes

Remove Background Color

# Usage: ipython --pdb removeColor.py 18
#! /usr/bin/env python
import itertools as it
import collections as ct
import cv2 as cv
import numpy as np
import pandas as pd


def calculate_top_color(image):
   a = image.copy()
   cnt = ct.Counter(a)
   topTen = cnt.most_common(10)
   topTenColors=[k for k,v in topTen]
   topColor=np.array(topTenColors).mean()
   return topColor

def replace_color(image, top=None, threshold=5, color=255):
   color_threshold = threshold
   a = image.copy()
   s = pd.Series(image.flatten())
   rows, cols = image.shape
   topColor0 = top or calculate_top_color(s)
   topColor = top or int(s.describe()['50%'])
   colorMin = topColor - color_threshold
   colorMax = topColor + color_threshold
   print(s.describe(), '\n', "TopColor: %s, %s\n" % (topColor, topColor0))
   for r in range(rows):
      for c in range(cols):
         val = a.item(r, c)
         if  colorMin <= val < colorMax:
            a.itemset((r, c), color)
   return a

def remove_top_color(img, top=None, threshold=18, color=255):
   b, g, r =img[:, :, 0], img[:, :, 1], img[:, :, 2]
   print("\nProcessing Color Channel: BLUE")
   b = replace_color(b, top, threshold, color)

   print("\nProcessing Color Channel: GREEN")
   g = replace_color(g, top, threshold, color)

   print("\nProcessing Color Channel: RED")
   r = replace_color(r, top, threshold, color)
   img0 = cv.merge((b, g, r))
   return img0


if __name__ == "__main__":
   import os,sys
   threshold = int(sys.argv[1]) if len(sys.argv) > 1 else 18
   # Load the image first
   img_path = './Signature.jpg'
   img0 = cv.imread(img_path)
   assert img0 is not None, "file could not be read, check with os.path.exists('%s')" % img_path

   cv.imwrite('Original.jpg', img0)
   img1 = remove_top_color(img0, threshold=threshold)
   cv.imwrite('Output.jpg', img1)
import itertools as it
import collections as ct
import cv2 as cv
import numpy as np
import pandas as pd

# Load the image first
img_path = './Signature.jpg'
img = cv.imread(img_path)
assert img is not None, "file could not be read, check with os.path.exists('%s')" % img_path

# Color Channels Splitting and merging
b, g, r =img[:, :, 0], img[:, :, 1], img[:, :, 2] # faster than cv.split(img)
a = b.flatten()
# Save the original image
img0 = cv.merge((b, g, r))
cv.imwrite('Original.jpg', img0)

# Using Python's collections.Counter()
import collections as ct
topTen = ct.Counter(a).most_common(10)

# Using Pandas for Number Analysis and Statistics
ss, df = pd.Series(a), pd.DataFrame(b)

# Pandas Descriptive statistics Summarizing data: describe
ss.describe()

# Pandas: **select specific percentiles**:
#    By default, the median is always included
percentiles = [0.05, 0.25, 0.75, 0.95]
ss.describe(percentiles=percentiles)

# Graystyle
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# bgSubtractor for background removal 
bgSuber = cv.bgsegm.createBackgroundSubtractorMOG()
bgSuber.apply(img)
bgSuber_img = bgSuber.apply(img)
cv.imwrite('bgSuber.jpg', bgSuber_img)
# Perform morphology operation
morph_kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
mask = cv.morphologyEx(bgSuber_img, cv.MORPH_CLOSE, morph_kernel)
res = cv.bitwise_and(img, img, mask=mask)
cv.imwrite('Result.jpg', res)

Accessing Image Properties

  • Image properties include "number of rows, columns, and channels"; "type of image data"; "number of pixels"; etc.
  • Note:
    • it is a good method to check whether the loaded image is grayscale or color.
    • img.dtype is very important while debugging,
      because a large number of errors in OpenCV-Python code are caused by invalid datatype.
#1. **Total number of pixels** is accessed by `img.size`:
#2. **Image datatype** is obtained by `img.dtype`:
#3. **shape of an image** is accessed by `img.shape`, It returns
#    a tuple of the number of rows, columns, and channels(if the image is color)
#    a tuple of the number of rows and columns ONLY**if an image is grayscale**. 
#    **check whether the loaded image is grayscale or color** first by Using `3 == len(img.shape)` .

print( img.shape, img.size, img.dtype)
(342, 548, 3)  562248  uint8

Splitting and Merging Image Channels

Sometimes you will need to work separately on the B,G,R channels of an image.

  • In this case, you need to split the BGR image into single channels.
  • In other cases, you may need to join these individual channels to create a BGR image.
  • Warning: cv.split() is a time costly operation. So use it only if necessary.
    Otherwise go for Numpy indexing.

You can do this simply by:

b, g, r = cv.split(img)
img = cv.merge((b, g, r))

# OR a better faster way by using **Numpy indexing**

b, g, r =img[:,:,0], img[:,:,0] img[:,:,0]
img = cv.merge((b, g, r))

# Suppose you want to set all the red pixels to zero
#   **Numpy indexing is faster**,
# so you do not need to split the channels first.:

img[:,:,2] = 0

Accessing and Modifying pixel values

You can access a pixel value by its row and column coordinates.

  • For BGR image, it returns an array of Blue, Green, Red values.
  • For grayscale image, just corresponding intensity is returned.
# Access a pixel value by its row and column coordinates
px = img[100, 100]
print( px )
[157 166 200] # an array of Blue, Green, Red values for BGR image
# accessing only blue pixel
blue = img[100, 100, 0]
print( blue )
157
#You can modify the pixel values the same way.
img[100, 100] = [255, 255, 255]
print( img[100, 100] )
[255 255 255]

# **Better pixel accessing and editing method** :

# accessing only RED value
img.item(10, 10, 2)
59
# modifying RED value
img.itemset((10, 10, 2), 100)
img.item(10, 10, 2)
100
  • Warning: Numpy is an optimized library for fast array calculations.
    So simply accessing each and every pixel value and modifying it will be very slow and it is discouraged.
  • Note
    • The above coordinates method is normally used for selecting a region of an array,
      say the first 5 rows and last 3 columns.
    • For individual pixel access, the Numpy array methods, array.item() and array.itemset() are considered better.
      They always return a scalar, however, so if you want to access all the B,G,R values, you will need to call array.item() separately for each value.

ROI of Image

Sometimes, you will have to play with certain regions of images. For eye detection in images:

  • first face detection is done over the entire image.
  • when a face is obtained, we select the face region alone and search for eyes inside it instead of searching the whole image. It improves:
    • accuracy, because eyes are always on faces 😄,
    • performance, because we search in a small area.

ROI is again obtained using Numpy indexing.

# Here I am selecting the ball and copying it to another region in the image:
ball = img[280:340, 330:390]
img[273:333, 100:160] = ball

Check the results below

Making Borders for Images (Padding)

If you want to create a border around an image, something like a photo frame,
you can use cv.copyMakeBorder(). But it has more applications for convolution operation, zero padding etc. This function takes following arguments:

  • src - input image
  • top, bottom, left, right - border width in number of pixels in corresponding directions
  • borderType - Flag defining what kind of border to be added. It can be following types:
    • cv.BORDER_CONSTANT - Adds a constant colored border. The value should be given as next argument.
    • cv.BORDER_REFLECT - Border will be mirror reflection of the border elements, like this : fedcba|abcdefgh|hgfedcb
    • cv.BORDER_REFLECT_101 or cv.BORDER_DEFAULT - Same as above, but with a slight change, like this : gfedcb|abcdefgh|gfedcba
    • cv.BORDER_REPLICATE - Last element is replicated throughout, like this: aaaaaa|abcdefgh|hhhhhhh
    • cv.BORDER_WRAP - Can't explain, it will look like this : cdefgh|abcdefgh|abcdefg
  • value - Color of border if border type is cv.BORDER_CONSTANT

Below is a sample code demonstrating all these border types for better understanding:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

BLUE = [255, 0, 0]

img1 = cv.imread('opencv-logo.png')
assert img1 is not None, "file could not be read, check with os.path.exists()"

replicate = cv.copyMakeBorder(img1, 10,10,10,10, cv.BORDER_REPLICATE)
reflect = cv.copyMakeBorder(img1, 10,10,10,10, cv.BORDER_REFLECT)
reflect101 = cv.copyMakeBorder(img1, 10,10,10,10, cv.BORDER_REFLECT_101)
wrap = cv.copyMakeBorder(img1, 10,10,10,10, cv.BORDER_WRAP)
constant= cv.copyMakeBorder(img1, 10,10,10,10, cv.BORDER_CONSTANT,value=BLUE)
plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL')
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')
plt.show()

See the result below. (Image is displayed with matplotlib. So RED and BLUE channels will be interchanged):

posted @   abaelhe  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示