图像变换dpi(tif->jpg),直方图均衡化,腐蚀膨胀,分水岭,模板匹配,直线检测

一.图像变换dpi

1.示例1

import numpy as np
from PIL import Image
import cv2
def test_dp():path='./gt_1.tif'# img=Image.open(path)# print(img.size)# print(img.info)img=cv2.imread(path)img=Image.fromarray(img)print(img.size)print(img.info)img.save('test.jpg', dpi=(300.0, 300.0), quality=40)
def test_dp2():path='./test.jpg'img=Image.open(path)print(img.size)print(img.info)if __name__ == '__main__':# test_dp()test_dp2()

2.示例2

#coding:utf-8
"""
生成的jpg大小在0.95到1.0之间
"""
import os
from PIL import Imagejpg_min_size = 0.95
jpg_max_size = 1.0
jpg_init_quality = 15
jpg_adjust_step = 3tif_list_path = './test/data/tif/002.tif'jpg_list_path = './002.jpg'img = Image.open(tif_list_path)img.convert("L").save(jpg_list_path, quality=jpg_init_quality, dpi=(300.0, 300.0))cur_quality = jpg_init_quality
op_cnt = 0while (os.path.getsize(jpg_list_path) * 1.0 / 1024 / 1024) < jpg_min_size:  # unit: metabytescur_quality += jpg_adjust_stepimg.convert("L").save(jpg_list_path, quality=cur_quality, dpi=(300.0, 300.0))op_cnt += 1
while (os.path.getsize(jpg_list_path) * 1.0 / 1024 / 1024) > jpg_max_size:  # unit: metabytescur_quality -= jpg_adjust_stepimg.convert("L").save(jpg_list_path, quality=cur_quality, dpi=(300.0, 300.0))op_cnt += 1print('tif:{}->jpg:{},调整次数:{},最终质量:{},最终大小:{}MB'.format(tif_list_path, jpg_list_path, op_cnt, cur_quality, os.path.getsize(jpg_list_path)/1024/1024))

二.直方图均衡化

对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内像素值的数量大致相等。输出图像的直方图是一个较平的分段直方图,从而提高图像的对比度。

2.1 灰度图直方图均衡

def Hist():img = cv2.imread('./data/timg.jpg', 0)  # 直接读为灰度图像res = cv2.equalizeHist(img)clahe = cv2.createCLAHE(clipLimit=2, tileGridSize=(10, 10))cl1 = clahe.apply(img)plt.subplot(131), plt.imshow(img, 'gray')plt.subplot(132), plt.imshow(res, 'gray')plt.subplot(133), plt.imshow(cl1, 'gray')plt.show()plt.hist(img.ravel(), 256, [0, 256])plt.hist(res.ravel(), 256, [0, 256])plt.hist(cl1.ravel(), 256, [0, 256])plt.show()

 灰度值的统计图

2.2 彩色图直方图均衡

import cv2image_src = cv2.imread('./lena.png')
r_image, g_image, b_image = cv2.split(image_src)r_image_eq = cv2.equalizeHist(r_image)
g_image_eq = cv2.equalizeHist(g_image)
b_image_eq = cv2.equalizeHist(b_image)image_eq = cv2.merge((r_image_eq, g_image_eq, b_image_eq))
cv2.imwrite('./image_eq.png', image_eq)

 三.腐蚀,膨胀

img_path='./image1200/small_disk800/result_result2_800/3272.jpg'
image = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
#gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
im = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)[1]
plt.imshow(im)
plt.show()
kernel = np.ones((7, 7), np.uint8)
dilation = cv2.dilate(im, kernel, iterations=1)
plt.imshow(dilation)
plt.show()
im = cv2.erode(dilation, kernel, iterations=1)
plt.imshow(im)
plt.show()

具体实现

a=np.array([[1,1,0,1,1],[1,1,0,1,1],[0,0,0,0,0],[1,1,0,1,1],[1,1,0,1,1]],dtype=np.float32)
kernel=np.array([[0,1,0],[1,1,1],[0,1,0]],dtype=np.uint8)
b=cv2.erode(a,kernel)
print(b)
c=cv2.dilate(a,kernel)
print(c)

四.分水岭

1.cv2.connectedComponents(gray_img, connectivity=None) 获取连通域
# connectivity 4或8 临近像素: 周围4像素或8像素

import cv2
import numpy as npimg = np.array([[0, 255, 0, 0],[0, 0, 0, 255],[0, 0, 0, 255],[255, 0, 0, 0]], np.uint8)
#获取连通域
ret, markers = cv2.connectedComponents(img)
print('===markers:\n', markers)

分水岭算法的整个过程,主要分为以下几步:

  1. 对图进行灰度化和二值化得到二值图像
  2. 通过膨胀得到确定的背景区域,通过距离转换得到确定的前景区域,剩余部分为不确定区域
  3. 对确定的前景图像进行连接组件处理,得到标记图像
  4. 根据标记图像对原图像应用分水岭算法,更新标记图像
import cv2
import numpy as np
import matplotlib.pyplot as pltsrc = cv2.imread("./1.png")
# cv2.imshow("input", src)
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
plt.hist(gray.ravel(), bins=100, range=[0, 255])
plt.show()
# # cv2.THRESH_OTSU 属于自适应阈值
# # cv2.THRESH_BINARY_INV属于黑白反转
binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# cv2.imshow("binary", binary)
cv2.imwrite('binary.jpg', binary)
#
# 形态学操作 得到3x3卷积核
se = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
print('se=', se)# 开运算去除图像中的细小白色噪点
open_img = cv2.morphologyEx(binary, cv2.MORPH_OPEN, se, iterations=2)
print('open_img=', open_img)
# # 膨胀
sure_bg = cv2.dilate(open_img, se, iterations=3)
cv2.imwrite('sure_bg.jpg', sure_bg)
#
# 距离变换,可以得到硬币的中心像素值最大(中心离背景像素最远), 从而白色区域肯定是硬币区域,而且还相互分离,得到确定的前景
dist_transform = cv2.distanceTransform(open_img, cv2.DIST_L2, 5)
sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)[1]cv2.imwrite('dist_transform.jpg', dist_transform)
cv2.imwrite('sure_fg.jpg', sure_fg)
#
#背景与前景相减得到不确定区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
cv2.imwrite('./unknown.jpg', unknown)# 将前景视为组件.进行连通组件标记 - 发现markers
ret, markers = cv2.connectedComponents(sure_fg)
markers = markers + 1
# print('===markers:\n', markers)
# 设定边缘待分割区域
markers[unknown == 255] = 0markers_copy = markers.copy()
markers_copy[markers == 0] = 150  # 灰色表示不确定区域
markers_copy[markers == 1] = 0    # 黑色表示背景
markers_copy[markers > 1] = 255   # 白色表示前景
markers_copy = np.uint8(markers_copy)
cv2.imwrite('./markers_copy.jpg', markers_copy)# 分水岭分割
markers = cv2.watershed(src, markers)
src[markers == -1] = [0, 0, 255]
cv2.imwrite('result.jpg', src)

            1.原图                                                      2.二值化

                    3.直方图                                       4.距离变换图     

  

                 5.背景图                                              6.前景图

       

7.未知区域(背景减前景)                       8.markers图(用来标记开始淹没的像素点)                                  9.结果图

 五.模板匹配

cv2.matchTemplate匹配函数返回的是一副灰度图,最白的地方表示最大的匹配。使用cv2.minMaxLoc()函数可以得到最大匹配值的坐标,以这个点为左上角角点,模板的宽和高画矩形就是匹配的位置了。

    lena_path='./lena.png'face_path='./face.png'img = cv2.imread(lena_path, 0)print(img.shape)template = cv2.imread(face_path, 0)print(template.shape)h, w = template.shape[:2]res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)print('res=',res.shape)cv2.imshow('res',res)cv2.waitKey(0)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)print('max_val=',max_val)left_top = max_loc  # 左上角right_bottom = (left_top[0] + w, left_top[1] + h)  # 右下角cv2.rectangle(img, left_top, right_bottom, 255, 2)  # 画出矩形位置cv2.imwrite('template.jpg',img)

                          res

六.直线检测

def compute_time_deco(function):def warpper(*args, **kwargs):st = time.time()res = function(*args, **kwargs)print('{}:spend time:{}'.format(function.__name__, time.time() - st))return resreturn warpper@compute_time_deco
def line_detection_center(image, name='./tmp.jpg'):"""得到最长直线的中心输入:图片输出:图片最长直线的中心"""if image.shape[-1] == 3:gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)else:gray = imagetry:img_bin = cv2.threshold(gray, 128, 255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]kernel_length = max(np.array(img_bin).shape[1] // 20, 1)hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_length, 1))# Morphological operation to detect horizontal lines from an imageimg_temp2 = cv2.erode(img_bin, hori_kernel, iterations=1)horizontal_lines_img = cv2.dilate(img_temp2, hori_kernel, iterations=2)#找最长的直线cnts = cv2.findContours(horizontal_lines_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)contours = cnts[0] if imutils.is_cv2() else cnts[1]c_ = sorted(contours, key=cv2.contourArea, reverse=True)long_line_cnt = np.squeeze(c_[0])x, y, w, h = cv2.boundingRect(long_line_cnt)debug = Trueif debug:# cv2.imwrite(name, horizontal_lines_img)# cv2.rectangle(image, (x, y), (x+w,y+h), color=(0, 0, 255), thickness=3)cv2.circle(img, (x+w//2, y+h//2), radius=10, color=(255, 0, 0), thickness=5)cv2.imwrite(name, image)# print('y+h//2:', y+h//2)return y+h//2except:return None

案例:找发票的线

#coding:utf-8
"""
fzh created on 2020/04/24
"""import cv2
import numpy as np
import imutils
import os
import pyzbar.pyzbar as pyzbar
import shutil
from scipy.signal import find_peaks, peak_widths
import timedebug_show = Truedef compute_time_deco(function):def warpper(*args, **kwargs):st = time.time()res = function(*args, **kwargs)print('{}:spend time:{}'.format(function.__name__, time.time() - st))return resreturn warpperdef get_contours_point(thresh,mode=0):"""0代表水平1代表垂直"""points = []cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)contours = cnts[0] if imutils.is_cv2() else cnts[1]contours = sorted(contours, key=cv2.contourArea, reverse=True)for contour in contours:x, y, w, h = cv2.boundingRect(contour)x1, y1, x2, y2 = x, y, x + w, y + hpoints.append([x1,y1,x2,y2])points = np.array(points)if len(points):if mode ==1 :#垂直return pointselse:#水平return points[points[:,1].argsort()]else:return points
##横线的中心处于10个像素以内就认为是同一高度,则进行合并
def merge_lines(points):centers = []for point in points:x1, y1, x2, y2 = pointcenters.append([(x1+x2)//2, (y1+y2)//2])opt = [0] * len(centers)for i in range(1, len(centers)):if abs(centers[i][-1] - centers[i - 1][-1]) <= 10:opt[i] = 1opt.append(0)index = [j for j in range(len(opt)) if opt[j] == 0]# print('index:', index)new_points = []for k in range(len(index) - 1):x1,y1,x2,y2 = min(points[index[k]:index[k + 1]][:,0]),min(points[index[k]:index[k + 1]][:,1]),\max(points[index[k]:index[k + 1]][:,-2]),max(points[index[k]:index[k + 1]][:,-1])new_points.append([x1,y1,x2,y2])# print(new_points)new_points = np.array(new_points)max_length_point = new_points[(new_points[:, -2] - new_points[:, 0]).argsort()[::-1]][0]fin_points = new_points[(new_points[:,-2]-new_points[:,0]).argsort()[::-1]][:5]fin_points = fin_points[fin_points[:, 1].argsort()]fix_points = []#最长线替代剩余线for point in fin_points:_, y1, _, y2 = pointfix_points.append([max_length_point[0], (y1+y2)//2, max_length_point[2], (y1+y2)//2])return fix_points
@compute_time_deco
def get_lines(img, name):"""输入图片返回水平线点 竖直线点 交点"""gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度图片# ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)  # 全局自适应阈值dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 101, 20)veri_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 30))veri_dilated = cv2.dilate(dst, veri_kernel, iterations=2)veri_eroded = cv2.erode(veri_dilated, veri_kernel, iterations=2)veri_thresh = cv2.adaptiveThreshold(veri_eroded, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 5)# cv2.imwrite('./veri_thresh.jpg', veri_thresh)hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 1))hori_dilated = cv2.dilate(dst, hori_kernel, iterations=2)hori_eroded = cv2.erode(hori_dilated, hori_kernel, iterations=2)hori_thresh = cv2.adaptiveThreshold(hori_eroded, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 5)# cv2.imwrite('./hori_thresh.jpg', hori_thresh)hori_points = get_contours_point(hori_thresh, mode=0)  # 0代表水平veri_points = get_contours_point(veri_thresh, mode=1)  # 1代表垂直hori_points = merge_lines(hori_points)cross_points = []delta = 10for veri_point in veri_points:vx1, vy1, vx2, vy2 = veri_pointfor hori_point in hori_points:hx1, hy1, hx2, hy2 = hori_pointif (hx1 - delta) <= vx1 <= (hx2 + delta) and (vy1 - delta) <= hy1 <= (vy2 + delta):cross_points.append((int(vx1), int(hy1)))cross_points = np.array(cross_points)# print('所有交点:', cross_points)print('交点总计:', len(cross_points))if debug_show:for i, point in enumerate(hori_points):# if i<1:x1, y1, x2, y2 = pointcv2.rectangle(img, (x1, y1), (x2, y2), color=(255, 0, 0), thickness=2)for i, point in enumerate(veri_points):# if i<1:x1, y1, x2, y2 = pointcv2.rectangle(img, (x1, y1), (x2, y2), color=(0, 255, 0), thickness=2)if len(cross_points):s = np.sum(cross_points, axis=1)table_x1, table_y1 = cross_points[np.argmin(s)]table_x2, table_y2 = cross_points[np.argmax(s)]cv2.circle(img, (table_x1, table_y1), 10, (0, 0, 255), thickness=2)cv2.circle(img, (table_x2, table_y2), 10, (0, 0, 255), thickness=2)cv2.imwrite(name, img)return hori_points, veri_points, cross_pointsdef test_lines():path = './电子发票方向矫正后的'output_path ='./电子发票画边和角点'if not os.path.exists(output_path):os.mkdir(output_path)imgs_list_path = [os.path.join(path,i) for i in os.listdir(path)]for i, img_list_path in enumerate(imgs_list_path):# if i<1:#     img_list_path = './电子发票方向矫正后的/test.png'img = cv2.imread(img_list_path)name = os.path.join(output_path, img_list_path.split('/')[-1])get_lines(img, name)if __name__ == '__main__':test_lines()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/493554.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CV中的经典网络模型

目标检测 目标检测&#xff0c;不仅要识别目标是什么&#xff08;分类&#xff09;&#xff0c;还要知道目标的具体位置&#xff08;可以当作回归来做&#xff09;。 RCNN Selective Search 算法获得候选框&#xff0c;Alexnet提取特征&#xff0c;SVM对每个候选框区域打分。…

技术阅读周刊第十一期

技术阅读周刊&#xff0c;每周更新。 历史更新 20231124&#xff1a;第七期20231201&#xff1a;第八期20231215&#xff1a;第十‍期 A Comprehensive guide to Spring Boot 3.2 with Java 21, Virtual Threads, Spring Security, PostgreSQL, Flyway, Caching, Micrometer, O…

数据智能是大数据的未来

来源&#xff1a;中国信息产业网 近日&#xff0c;两家大数据领域的代表性企业Cloudera和Hortonworks宣布了它们相对平等的合并&#xff0c;宣称新公司将创建世界领先的下一代数据平台并提供业界首个企业数据云&#xff0c;这令很多人感到意外&#xff0c;大数据的未来何去何从…

利用GAN原始框架生成手写数字

这一篇GAN文章只是让产生的结果尽量真实&#xff0c;还不能分类。 本次手写数字GAN的思想&#xff1a; 对于辨别器&#xff0c;利用真实的手写数字&#xff08;真样本&#xff0c;对应的标签为真标签&#xff09;和随机噪声经过生成器产生的样本&#xff08;假样本&#xff0…

DL也懂纹理吗——图像的纹理特征

工作中遇到一个问题&#xff1a;对于同一场景&#xff0c;训练好的DL模型能把大部分样本分类准确&#xff0c;而对于少量负样本&#xff0c;DL会错分到另外一个对立的类中。错分的样本可以认为是难分的样本&#xff0c;但是我们还想知道这两种样本到底是哪里的差异导致DL做出了…

排序算法--(冒泡排序,插入排序,选择排序,归并排序,快速排序,桶排序,计数排序,基数排序)

一.时间复杂度分析 - **时间复杂度**&#xff1a;对排序数据的总的操作次数。反应当n变化时&#xff0c;操作次数呈现什么规律 - **空间复杂度**&#xff1a;算法在计算机内执行时所需要的存储空间的容量&#xff0c;它也是数据规模n的函数。 1.例题: 有一个字符串数组&…

肠里细菌“肚里蛔虫”:肠脑研究缘何越来越热

来源&#xff1a;科学网最懂你大脑的&#xff0c;可能不是“肚子里的蛔虫”&#xff0c;而是肠子里的细菌——肠道菌群对神经系统、心理和行为方面的影响正成为一个新兴热点领域。在日前举办的美国神经科学学会年会上&#xff0c;一张海报上的大脑切片显微镜图像显示&#xff0…

SVM原理与实战

先看线性可分问题。对于线性可分&#xff0c;其实感知机就可以解决。但是感知机只是找到一个超平面将数据分开&#xff0c;而这样的超平面可能是平行的无限多个&#xff0c;我们需要在这其中找到最优的一个。怎么衡量一个超平面是不是最优的呢&#xff0c;直观上讲&#xff0c;…

2014-01-01

一:HyperlinkButton点击后打开新窗口的方法 1,直接在界面中写这段代码就可以了: <HyperlinkButton NavigateUri"http://www.cnblogs.com/wsdj-ITtech/" Content"Click Me" TargetName"_blank" FontSize"28" Height"50"…

李飞飞高徒:斯坦福如何打造基于视觉的智能医院?

作者&#xff1a;Albert Haque、Michelle Guo来源&#xff1a;机器之心自 2009 年担任斯坦福人工智能实验室和视觉实验室的负责人&#xff0c;李飞飞在推动计算机视觉方面研究的同时&#xff0c;还密切关注 AI 医疗的发展。昨日&#xff0c;李飞飞离任斯坦福 AI 实验室负责人一…

tensorflow知识点

一.bazel编译tensorflow注意版本号: 在/tensorflow/tensorflow/configure.py 查看bazel版本号 https://github.com/tensorflow/tensorflow https://github.com/bazelbuild/bazel/releases?after0.26.1 https://tensorflow.google.cn/ 二&#xff0c;基础知识点 1.打印出…

eclipse中如何导入jar包

如图&#xff0c;首先右键点击项目&#xff0c;选择最下面的properties&#xff0c; 然后进去之后点击java build path&#xff0c;右边会出来4个选项卡&#xff0c;选择libraries&#xff0c; 这时候最右边会有多个选项&#xff0c;第一个add jars是添加项目文件中的jar包&…

线性-LR-softmax傻傻分不清楚

softmax 对于分类网络&#xff0c;最后一层往往是全连接层&#xff0c;如果是N分类&#xff0c;那么最终的全连接层有N个结点。很显然&#xff0c;每个节点对应一个类&#xff0c;该节点的权重越大&#xff0c;说明网络越倾向于认为输入样本属于该类。这其实就是Softmax的思想…

一图看懂国外智能网联汽车传感器产业发展!

来源&#xff1a;赛迪智库编辑&#xff1a;煜 佳未来智能实验室是人工智能学家与科学院相关机构联合成立的人工智能&#xff0c;互联网和脑科学交叉研究机构。未来智能实验室的主要工作包括&#xff1a;建立AI智能系统智商评测体系&#xff0c;开展世界人工智能智商评测&#…

深度学习中的信息论——交叉熵

信息量 可以说就信息量是在将信息量化。首先信息的相对多少是有切实体会的&#xff0c;有的人一句话能包含很多信息&#xff0c;有的人说了等于没说。我们还可以直观地感觉到信息的多少和概率是有关的&#xff0c;概率大的信息也相对低一些。为了量化信息&#xff0c;一个做法…

传统手工特征--opencv

一&#xff0c;颜色特征&#xff1a; 简单点来说就是将一幅图上的各个像素点颜色统计出来&#xff0c;适用颜色空间&#xff1a;RGB&#xff0c;HSV等颜色空间&#xff0c; 具体操作&#xff1a;量化颜色空间&#xff0c;每个单元&#xff08;bin&#xff09;由单元中心代表&…

特写李飞飞:她激励了人工智能的发展,更要给人工智能赋予人的价值

文 | MrBear 编辑 | 杨晓凡来源&#xff1a;雷锋网摘要&#xff1a;李飞飞无疑是人工智能界最响亮的名字之一。她既对机器学习领域的发展做出了杰出的贡献&#xff0c;也是普通大众眼中温和的人工智能技术宣扬者&#xff0c;还是谷歌这一科技巨头的人工智能技术领导人之一。WI…

Chap-4 Section 4.2.4 指令修正方式

对于X86平台下的ELF文件的重定位入口所修正的指令寻址方式只有两种&#xff1a;绝对近址32寻址和相对近址32寻址。 这两种指令修正方式每个被修正的位置的长度都为32位&#xff0c;即4个字节&#xff0c;而且都是近址寻址&#xff0c;不用考虑Intel的段间远址寻址。r_info成员的…

没见过女人的小和尚——SVDD

是的&#xff0c;即便是出生在山上的小和尚&#xff0c;从来没有下过山&#xff0c;没有见过女人&#xff0c;但是一旦有女施主上山&#xff0c;小和尚依然可以轻松地区分出眼前的人是如此不同。 传统的SVM是寻找一个超平面&#xff0c;而SVDD寻找的超平面更进一步&#xff0c…

解读GAN及其 2016 年度进展

作者&#xff1a;程程 链接&#xff1a;https://zhuanlan.zhihu.com/p/25000523 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 GAN&#xff0c;全称为Generative Adversarial Nets&#xff0c;直译为生成式对抗网络…