图像处理笔记0-大杂烩

本文记录了日常中经常用到的一些图像操作,内容有些杂乱,还未好好梳理,所以,先挑自己需要的借鉴。等记录到一定内容,再对本文的结构做一个较大的修改。

目录

一、统计运算时间

1.1、法1:datetime

1.2、法2:time

二、图像操作

2.1、padding操作、base64encode操作

2.1、文件名包含中文读取

三、各种图像格式之间的转换

3.1、bytes与base64互转

3.2、bytes与Image对象互转

3.3、bytes与CV2对象互转

3.4、base64与Image对象互转

3.5、base64与cv2对象互转

3.6、image与cv2对象互转

四、视频文件转单帧图像保存

五、图像显示

5.1、中文字符绘制到图像上

六、图像保存

七、其他操作

7.1、计算两条直线的角度

7.2、根据偏移角度,进行摆正

参考内容



一、统计运算时间

1.1、法1:datetime

这是微秒的单词,1秒(s) =1000 毫秒(ms/millisecond) = 1,000,000 微秒(μs/microseconds) 
import datetime

starttime = datetime.datetime.now()
endtime = datetime.datetime.now()

elased_time =endtime - starttime
print('***********:', elased_time)              # 打印内容:0:00:01.181709

elased_time_m = (endtime - starttime).microseconds
print('***********微秒:', elased_time_m)			# 打印内容:181709

elased_time_s = (endtime - starttime).seconds 
print('***********秒:', elased_time_s)           # 打印内容:1

one_time = elased_time_s + elased_time_m / 1000000
print('**********', one_time)                    # 打印内容:1.181709

 打印结果:

***********微秒: 164341
***********秒: 1
********** 1.164341

可以看出来,他是根据后缀来区分取哪部分的:

  1. 无后缀,直接输出完成时间
  2. 后缀microseconds, 输出微秒单位部分时间
  3. 后缀seconds, 输出秒单位部分时间

注意:完整的时间,是elased_time_s+elased_time_m/1000000

1.2、法2:time

import time

starttime = time.time()
elased_time = time.time() - starttime
print('***********秒:', elased_time)

注意:输出的单位,是秒

二、图像操作

2.1、padding操作、base64encode操作

import base64
image_path = r'1.png'
import base64
from PIL import Image
import io
import numpy as np
import cv2

def padding(arr):
    h, w = arr.shape[:2]
    p1 = abs(int((h - w) / 2))
    p2 = abs(h - w) - p1
    if h < w:
        arr = np.pad(arr, ((p1, p2), (0, 0), (0, 0)), mode='constant')
    if h > w:
        arr = np.pad(arr, ((0, 0), (p1, p2), (0, 0)), mode='constant')
    return arr

def base64encode_img(image_path):
    img = cv2.imread(image_path)
    raw_w, raw_h, _ = img.shape
    print('0:', raw_h, raw_w)
    img = padding(img)
    print('1:', img.shape)

    img = cv2.resize(img, (512, 512), interpolation=cv2.INTER_CUBIC)
    print('2:', img.shape)

    src_image = Image.fromarray(img)
    output_buffer = io.BytesIO()
    src_image.save(output_buffer, format='JPEG')
    byte_data = output_buffer.getvalue()
    base64_str = base64.b64encode(byte_data).decode('utf-8')
    return base64_str

base64_str = base64encode_img(image_path)
print(base64_str)

2.1、文件名包含中文读取

def cv_imread(file_path):
    cv_img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), 1)
    return cv_img

三、各种图像格式之间的转换

3.1、bytes与base64互转

# bytes转base64
image_base4 = base64.b64encode(image_bytes).decode('utf8')
 
# base64转bytes
image_bytes = base64.b64decode(image_base64)

3.2、bytes与Image对象互转

#将bytes结果转化为Image
bytes_stream = io.BytesIO(result)
roiimg = Image.open(bytes_stream)
 
# 将Image转为bytes
img = Image.open(img_path, mode='r')
imgByteArr = io.BytesIO()

3.3、bytes与CV2对象互转

# cv2图片对象转为bytes
img = cv2.imread(img_path)
array_bytes = img.tobytes()
 
# bytes转为cv2图片对象
img_buffer_numpy = np.frombuffer(img_bytes, dtype=np.uint8) 
img_numpy = cv2.imdecode(img_buffer_numpy, 1)

3.4、base64与Image对象互转

# Image转base64
img_buffer = io.BytesIO()
image.save(img_buffer, format='JPEG')
byte_data = img_buffer.getvalue()
base64_str = base64.b64encode(byte_data)
 
# base64转Image
image = base64.b64decode(base64_str)
image = BytesIO(image)
image = Image.open(image)

3.5、base64与cv2对象互转

#cv2转base64
base64_str = cv2.imencode('.jpg',image)[1].tostring()
base64_str = base64.b64encode(base64_str)
 
 
#base64转cv2
imgString = base64.b64decode(base64_str)
nparr = np.fromstring(imgString,np.uint8)  
image = cv2.imdecode(nparr,cv2.IMREAD_COLOR)

3.6、image与cv2对象互转

# Iamge 转 cv2
img = Image.open("test.jpg")
img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
 
# cv2 转 Image
img = cv2.imread("test.jpg")
img = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))

四、视频文件转单帧图像保存

__author__ = "lingjun"
# E-mail: 1763469890@qq.com

import cv2
 
vidcap = cv2.VideoCapture('D:\car\car.avi')
success,image = vidcap.read()
count = 0
success = True
while success:
  success,image = vidcap.read()
  cv2.imwrite("frame%d.jpg" % count, image)     # save frame as JPEG file
  if cv2.waitKey(10) == 27:
      break
  count += 1

五、图像显示

5.1、中文字符绘制到图像上

def change_cv2_draw(image,strs,local,colour):
    pilimg = Image.fromarray(image)
    draw = ImageDraw.Draw(pilimg)
    SimHei_ttf = os.path.join(r'pre-trained_PSPNet', 'SimHei.ttf')
    font = ImageFont.truetype(SimHei_ttf, 20, encoding="utf-8")
    draw.text(local, strs, colour, font=font)
    image = np.array(pilimg)
    return image

kernel = np.ones((5, 5), np.uint8)
pred_seged = cv2.morphologyEx(img_seged.astype(np.uint8), cv2.MORPH_CLOSE, kernel)

_, img_seged_p = cv2.threshold(pred_seged, 127, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(img_seged_p, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

out_img = img.copy()
if len(contours) > 0:
     for contour in contours:
         area = cv2.contourArea(contour)
         if area > 200:
            rect = cv2.minAreaRect(contour)
            box = np.int0(cv2.boxPoints(rect))
            y1, x1, y2, x2 = np.min(box[:, 1]), np.min(box[:, 0]), np.max(box[:, 1]), np.max(box[:, 0])
            cv2.rectangle(out_img, (x1, y1), (x2, y2), (255, 0, 0), 1)
            out_img = change_cv2_draw(out_img, '异物', (int(x1), int(y1-25)), (255, 0, 0))

六、图像保存

import cv2
cv2.imwrite()
输入图像范围在0~255之间。

from matplotlib import pyplot as plt
plt.imsave();
输入图像范围在0~1之间。

from skimage import io
io.imsave();
输入图像范围在0~255之间。

之所以会发现他们之间对图像保存的不同,主要是因为在对同一一个array数组进行保存时候发现,保存的结果是不同的。例如:

  • 保存的数组范围是0-1,你用cv2.imwrite(),保存的图像几乎都是黑的;
  • 但是你用plt.imsave()保存的图像,却是对比度差异很大的黑白二值图像

七、其他操作

7.1、计算两条直线的角度

已知:

  • 组成直线l1的点(x1-1, y1-1) (x1-2, y1-2)
  • 组成直线l2的点(x2-1, y2-1) (x2-2, y2-2)
  • 求l1和l2的角度?

代码实现:

import numpy as np
class Point:
    x = 0
    y = 0

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

class Line:
    def __init__(self, p1, p2):
        self.p1 = p1
        self.p2 = p2


def GetCrossAngle(l1, l2):
    arr_0 = np.array([(l1.p2.x - l1.p1.x), (l1.p2.y - l1.p1.y)])
    arr_1 = np.array([(l2.p2.x - l2.p1.x), (l2.p2.y - l2.p1.y)])
    cos_value = (float(arr_0.dot(arr_1)) / (np.sqrt(arr_0.dot(arr_0)) * np.sqrt(arr_1.dot(arr_1))))
    return np.round(np.arccos(cos_value) * (180 / np.pi), 1)

line1 = Line(Point(0, 0), Point(0, 512))
line2 = Line(Point(0, 0), Point(512, 0))    # 基准线 水平线
"""
  (0, 0)                     (512, 0)
---|--------------------------*->   x
   |  *
   |    *
   |      *
   |        *
   |          *
   |            *
   |              *
   |                 * 
   |                   *
   |                     *
   |                       *
   *(0, 512)                 *(512, 512)
   ↓
   y
"""

# 测1
angle = GetCrossAngle(line1, line2)  # 计算得到的角度

print('angle:', angle)

output:
angle: 90.0

# 测2
line1 = Line(Point(0, 0), Point(512, 512))
line2 = Line(Point(0, 0), Point(512, 0))    # 基准线 水平线
angle = GetCrossAngle(line1, line2)  # 计算得到的角度

print('angle:', angle)

output:
angle: 45.0

7.2、根据偏移角度,进行摆正

代码实现:

import cv2
# 旋转angle角度,缺失背景白色(255, 255, 255)填充
def rotate_bound_bg(image, angle):
    """
    :param image: 待旋转图像
    :param angle: 角度,  顺时针旋转为+, 逆时针旋转为-
    :return:
    """
    # grab the dimensions of the image and then determine the center
    (h, w) = image.shape[:2]
    (cX, cY) = (w // 2, h // 2)

    # grab the rotation matrix (applying the negative of the angle to rotate clockwise), then grab the sine and cosine
    # (i.e., the rotation components of the matrix)
    # -angle位置参数为角度参数负值表示顺时针旋转; 1.0位置参数scale是调整尺寸比例(图像缩放参数),建议0.75
    M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])

    # compute the new bounding dimensions of the image
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))

    # adjust the rotation matrix to take into account translation
    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY

    # perform the actual rotation and return the image
    # borderValue 缺失背景填充色彩,可自定义, borderValue 缺省,默认是黑色(0, 0 , 0)
    return cv2.warpAffine(image, M, (nW, nH), borderValue=(170, 170, 170))

angle = angle-90
dst = rotate_bound_white_bg(dst, angle)
cv2.imwrite(os.path.join(save_dir, name), dst)

结果展示:

 注意:由于我这里是按竖直方向摆正,所以减去了90度,这样恰好可以确定是顺时针,还是逆时针偏转。

参考内容

  1. SimHei.ttf简体字文件下载地址:https://download.youkuaiyun.com/download/wsLJQian/25660904
  2. 参考链接:python中各种图像格式之间的转换_LOONGV的博客-优快云博客_python转换图片格式https://blog.youkuaiyun.com/u013032852/article/details/120321687
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钱多多先森

你的鼓励,是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值