利用openCV或其他工具编写程序实现对图片中框选出的图片测量其宽度。
实现过程
1、编写程序
目标图片如下
根据展示的程序功能编写对应的程序:
第一步,读取显示图像的功能openCV已经提供了函数imread()和imshow(),代码如下
import cv2
import numpy as np
img=cv2.imread('test4.bmp')
cv2.imshow('origin',img)
cv2.waitKey(0)
第二步,在图像上框选图像片段,这里我使用的是open CV中的cv2.selectROI()函数来实现对图像的框选操作,并将框选出的图片分割出来:
r=cv2.selectROI(img,False,False)
imCrop = img[int(r[1]):int(r[1]+r[3]), int(r[0]):int(r[0]+r[2])]
第三步,对分割出来的图像进行灰度、二值化、边缘检测的操作:
grayimg=cv2.cvtColor(imCrop,cv2.COLOR_BGR2GRAY)
cv2.imshow('gray',grayimg)
cv2.waitKey(0)
ret,thres=cv2.threshold(grayimg,80,255,cv2.THRESH_BINARY_INV)
cv2.imshow('thres',thres)
cv2.waitKey(0)
imgcanny=cv2.Canny(thres,80,255)
ret,thresh=cv2.threshold(imgcanny,80,255,cv2.THRESH_BINARY_INV)
cv2.imshow('imgcanny',thresh)
cv2.waitKey(0)
第四步,将处理后的图片贴回原图片上,这里通过切片的方式将图像贴回原位置:
img3=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img3[int(r[1]):int(r[1]+r[3]), int(r[0]):int(r[0]+r[2])]=res
cv2.imshow('result', img3)
cv2.waitKey(0)
第五步,计算切割部分图像的宽度,通过cv2. boundingRect()函数得到图像的顶点坐标,并赋值给x,y,w,h,再通过cv2.moments()函数测量宽,最后将结果通过cv2.putText()函数打在图片上:
def measure_demo(image,img):
ret, binary = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
contours, hireachy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for i, contour in enumerate(contours):
area = cv2.contourArea(contour)
x, y, w, h = cv2.boundingRect(contour)
mm = cv2.moments(contour)
cx = mm['m10'] / mm['m00']
cy = mm['m01'] / mm['m00']
height=h/0.44
weight=w/0.44
img = cv2.putText(img, 'h={}'.format(height) ,(5,15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255, 0), 1)
cv2.imshow("measure-contours2", img)
cv2.waitKey(0)
运行结果
问题及解决方法
1、在图像上随意框选
解决方法:在查找到ROI方法之前,我试过使用切片的方法,如img1=img[120:230,80:238] ,使用这种方法得到的结果在我看来并不够“随意”,随后我花了大量时间查找资料,找到了ROI方法可以在图像上任意框选我想框选的地方,实现了“随意”。
2、任意框选图片后出现程序未响应的情况
解决方法:这个问题其实困扰了我很久,每次都卡在框选后的未响应状态,后来查了资料后发现,我出现这种情况有两个原因:一是我框选了图片后没有确定我所选择的图片,每次框选之后我们都需要按下空格或是回车键来确定自己所选的图片;二是选完图片后我会习惯性的关掉图像窗口,但当我们看jupyter前面的[]时会发现,在关掉窗口前,确认图片后,[]中的*已经变为了数字,也就是说ROI方法与imshow()不一样,它不需要你去关掉窗口进行下一步,相反,只有当你进行了下一步,你才能关掉ROI的图像窗口,所以每当我尝试关掉ROI的图像窗口时,它都会显示程序未响应。
实验总结
这一次的实验在我看来难度相较于上一个实验高了很多,需要思考的地方也很多,如怎样随意框选图片、怎么在无参照物的情况下计算宽度、怎样在原图像上只对框选部位进行操作,我觉得我的解决方案更多的是取巧,我并没有在原图像上进行操作,而是将其切割下来处理完后再“贴”回去,但我觉得这是我的一种想法,它锻炼了我对问题的思考方式,也许这不是最好的方法,但这是我目前能做到的最好的方法。希望以后的我有机会重新做一次这个实验,带着新的思维新的方式。